summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md19
-rw-r--r--CONTRIBUTING.md75
-rw-r--r--Pipfile1
-rw-r--r--README.md2
-rw-r--r--data/configd-include.json2
-rw-r--r--data/templates/accel-ppp/config_ip_pool.j22
-rw-r--r--data/templates/accel-ppp/pppoe.config.tmpl22
-rw-r--r--data/templates/conserver/dropbear@.service.tmpl4
-rw-r--r--data/templates/dhcp-client/daemon-options.tmpl2
-rw-r--r--data/templates/dhcp-server/dhcpd.conf.tmpl18
-rw-r--r--data/templates/dhcp-server/dhcpdv6.conf.tmpl6
-rw-r--r--data/templates/firewall/nftables-nat66.tmpl37
-rw-r--r--data/templates/frr/bfd.frr.tmpl56
-rw-r--r--data/templates/frr/bgp.frr.tmpl70
-rw-r--r--data/templates/frr/ospf.frr.tmpl7
-rw-r--r--data/templates/frr/ospfv3.frr.tmpl43
-rw-r--r--data/templates/frr/rpki.frr.tmpl4
-rw-r--r--data/templates/frr/static.frr.tmpl17
-rw-r--r--data/templates/frr/static_routes_macro.j26
-rw-r--r--data/templates/frr/vrf.frr.tmpl22
-rw-r--r--data/templates/https/nginx.default.tmpl1
-rw-r--r--data/templates/syslog/rsyslog.conf.tmpl58
-rw-r--r--debian/changelog4
-rw-r--r--debian/control1
-rw-r--r--interface-definitions/dhcpv6-server.xml.in20
-rw-r--r--interface-definitions/dns-domain-name.xml.in2
-rw-r--r--interface-definitions/include/accel-auth-local-users.xml.i4
-rw-r--r--interface-definitions/include/accel-auth-mode.xml.i4
-rw-r--r--interface-definitions/include/accel-auth-protocols.xml.i4
-rw-r--r--interface-definitions/include/accel-client-ip-pool-start-stop.xml.i4
-rw-r--r--interface-definitions/include/accel-client-ip-pool-subnet.xml.i4
-rw-r--r--interface-definitions/include/accel-client-ipv6-pool.xml.i4
-rw-r--r--interface-definitions/include/accel-gateway-address.xml.i4
-rw-r--r--interface-definitions/include/accel-lcp-echo-interval-failure.xml.i4
-rw-r--r--interface-definitions/include/accel-lcp-echo-timeout.xml.i4
-rw-r--r--interface-definitions/include/accel-mtu-128-16384.xml.i4
-rw-r--r--interface-definitions/include/accel-name-server.xml.i4
-rw-r--r--interface-definitions/include/accel-ppp-mppe.xml.i4
-rw-r--r--interface-definitions/include/accel-radius-additions-disable-accounting.xml.i4
-rw-r--r--interface-definitions/include/accel-radius-additions-rate-limit.xml.i4
-rw-r--r--interface-definitions/include/accel-radius-additions.xml.i4
-rw-r--r--interface-definitions/include/accel-wins-server.xml.i4
-rw-r--r--interface-definitions/include/address-ipv4-ipv6-dhcp.xml.i4
-rw-r--r--interface-definitions/include/address-ipv4-ipv6.xml.i4
-rw-r--r--interface-definitions/include/bfd-common.xml.i72
-rw-r--r--interface-definitions/include/bgp-afi-l2vpn-common.xml.i14
-rw-r--r--interface-definitions/include/bgp-afi-peer-group.xml.i7
-rw-r--r--interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i21
-rw-r--r--interface-definitions/include/bgp-neighbor-afi-l2vpn-evpn.xml.i16
-rw-r--r--interface-definitions/include/bgp-route-map.xml.i10
-rw-r--r--interface-definitions/include/bgp-shutdown.xml.i8
-rw-r--r--interface-definitions/include/bgp/bgp-afi-aggregate-address.xml.i (renamed from interface-definitions/include/bgp-afi-aggregate-address.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-allowas-in.xml.i (renamed from interface-definitions/include/bgp-afi-allowas-in.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-attribute-unchanged.xml.i (renamed from interface-definitions/include/bgp-afi-attribute-unchanged.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-capability-orf.xml.i (renamed from interface-definitions/include/bgp-afi-capability-orf.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-common.xml.i (renamed from interface-definitions/include/bgp-afi-common.xml.i)24
-rw-r--r--interface-definitions/include/bgp/bgp-afi-ipv4-prefix-list.xml.i (renamed from interface-definitions/include/bgp-afi-ipv4-prefix-list.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-ipv6-nexthop-local.xml.i (renamed from interface-definitions/include/bgp-afi-ipv6-nexthop-local.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-ipv6-prefix-list.xml.i (renamed from interface-definitions/include/bgp-afi-ipv6-prefix-list.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-l2vpn-common.xml.i27
-rw-r--r--interface-definitions/include/bgp/bgp-afi-maximum-paths.xml.i33
-rw-r--r--interface-definitions/include/bgp/bgp-afi-nexthop-self.xml.i (renamed from interface-definitions/include/bgp-afi-nexthop-self.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-redistribute-metric-route-map.xml.i (renamed from interface-definitions/include/bgp-afi-redistribute-metric-route-map.xml.i)6
-rw-r--r--interface-definitions/include/bgp/bgp-afi-route-map.xml.i (renamed from interface-definitions/include/bgp-afi-route-map.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-route-reflector-client.xml.i (renamed from interface-definitions/include/bgp-afi-route-reflector-client.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-route-server-client.xml.i (renamed from interface-definitions/include/bgp-afi-route-server-client.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-afi-soft-reconfiguration.xml.i (renamed from interface-definitions/include/bgp-afi-soft-reconfiguration.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-bfd.xml.i (renamed from interface-definitions/include/bgp-bfd.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-capability.xml.i (renamed from interface-definitions/include/bgp-capability.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-common-config.xml.i825
-rw-r--r--interface-definitions/include/bgp/bgp-description.xml.i (renamed from interface-definitions/include/bgp-description.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-disable-capability-negotiation.xml.i (renamed from interface-definitions/include/bgp-disable-capability-negotiation.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-disable-connected-check.xml.i (renamed from interface-definitions/include/bgp-disable-connected-check.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-ebgp-multihop.xml.i (renamed from interface-definitions/include/bgp-ebgp-multihop.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-local-as.xml.i (renamed from interface-definitions/include/bgp-local-as.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-neighbor-afi-ipv4-unicast.xml.i (renamed from interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i)11
-rw-r--r--interface-definitions/include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i20
-rw-r--r--interface-definitions/include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i16
-rw-r--r--interface-definitions/include/bgp/bgp-override-capability.xml.i (renamed from interface-definitions/include/bgp-override-capability.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-passive.xml.i (renamed from interface-definitions/include/bgp-passive.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-password.xml.i (renamed from interface-definitions/include/bgp-password.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-peer-group.xml.i (renamed from interface-definitions/include/bgp-peer-group.xml.i)7
-rw-r--r--interface-definitions/include/bgp/bgp-remote-as.xml.i (renamed from interface-definitions/include/bgp-remote-as.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-route-target.xml.i45
-rw-r--r--interface-definitions/include/bgp/bgp-shutdown.xml.i8
-rw-r--r--interface-definitions/include/bgp/bgp-timers-holdtime.xml.i (renamed from interface-definitions/include/bgp-timers-holdtime.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-timers-keepalive.xml.i (renamed from interface-definitions/include/bgp-timers-keepalive.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-ttl-security.xml.i (renamed from interface-definitions/include/bgp-ttl-security.xml.i)4
-rw-r--r--interface-definitions/include/bgp/bgp-update-source.xml.i (renamed from interface-definitions/include/bgp-update-source.xml.i)5
-rw-r--r--interface-definitions/include/certificate-ca.xml.i4
-rw-r--r--interface-definitions/include/certificate-key.xml.i4
-rw-r--r--interface-definitions/include/certificate.xml.i4
-rw-r--r--interface-definitions/include/dhcp-options.xml.i16
-rw-r--r--interface-definitions/include/dhcp-server-domain-search.xml.i4
-rw-r--r--interface-definitions/include/dhcpv6-options.xml.i4
-rw-r--r--interface-definitions/include/generic-disable-node.xml.i4
-rw-r--r--interface-definitions/include/interface-arp-cache-timeout.xml.i4
-rw-r--r--interface-definitions/include/interface-description.xml.i4
-rw-r--r--interface-definitions/include/interface-dial-on-demand.xml.i4
-rw-r--r--interface-definitions/include/interface-disable-arp-filter.xml.i4
-rw-r--r--interface-definitions/include/interface-disable-forwarding.xml.i4
-rw-r--r--interface-definitions/include/interface-disable-link-detect.xml.i4
-rw-r--r--interface-definitions/include/interface-disable.xml.i4
-rw-r--r--interface-definitions/include/interface-eapol.xml.i4
-rw-r--r--interface-definitions/include/interface-enable-arp-accept.xml.i4
-rw-r--r--interface-definitions/include/interface-enable-arp-announce.xml.i4
-rw-r--r--interface-definitions/include/interface-enable-arp-ignore.xml.i4
-rw-r--r--interface-definitions/include/interface-enable-proxy-arp.xml.i4
-rw-r--r--interface-definitions/include/interface-hw-id.xml.i4
-rw-r--r--interface-definitions/include/interface-ipv4-options.xml.i4
-rw-r--r--interface-definitions/include/interface-ipv6-options.xml.i4
-rw-r--r--interface-definitions/include/interface-mac.xml.i4
-rw-r--r--interface-definitions/include/interface-mirror.xml.i4
-rw-r--r--interface-definitions/include/interface-mtu-1200-16000.xml.i4
-rw-r--r--interface-definitions/include/interface-mtu-1450-16000.xml.i4
-rw-r--r--interface-definitions/include/interface-mtu-64-8024.xml.i4
-rw-r--r--interface-definitions/include/interface-mtu-68-1500.xml.i4
-rw-r--r--interface-definitions/include/interface-mtu-68-16000.xml.i4
-rw-r--r--interface-definitions/include/interface-parameters-dont-fragment.xml.i8
-rw-r--r--interface-definitions/include/interface-parameters-flowlabel.xml.i15
-rw-r--r--interface-definitions/include/interface-parameters-key.xml.i15
-rw-r--r--interface-definitions/include/interface-parameters-tos.xml.i16
-rw-r--r--interface-definitions/include/interface-parameters-ttl.xml.i20
-rw-r--r--interface-definitions/include/interface-proxy-arp-pvlan.xml.i4
-rw-r--r--interface-definitions/include/interface-source-validation.xml.i4
-rw-r--r--interface-definitions/include/interface-vrf.xml.i4
-rw-r--r--interface-definitions/include/interface-xdp.xml.i4
-rw-r--r--interface-definitions/include/ipv6-address-autoconf.xml.i4
-rw-r--r--interface-definitions/include/ipv6-address-eui64.xml.i4
-rw-r--r--interface-definitions/include/ipv6-address-no-default-link-local.xml.i4
-rw-r--r--interface-definitions/include/ipv6-address.xml.i4
-rw-r--r--interface-definitions/include/ipv6-disable-forwarding.xml.i4
-rw-r--r--interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i4
-rw-r--r--interface-definitions/include/isis-redistribute-ipv4.xml.i4
-rw-r--r--interface-definitions/include/listen-address-ipv4.xml.i4
-rw-r--r--interface-definitions/include/listen-address.xml.i4
-rw-r--r--interface-definitions/include/nat-address.xml.i4
-rw-r--r--interface-definitions/include/nat-interface.xml.i4
-rw-r--r--interface-definitions/include/nat-port.xml.i4
-rw-r--r--interface-definitions/include/nat-rule.xml.i4
-rw-r--r--interface-definitions/include/nat-translation-port.xml.i4
-rw-r--r--interface-definitions/include/ospf/ospf-authentication.xml.i (renamed from interface-definitions/include/ospf-authentication.xml.i)4
-rw-r--r--interface-definitions/include/ospf/ospf-common-config.xml.i761
-rw-r--r--interface-definitions/include/ospf/ospf-distance-global.xml.i14
-rw-r--r--interface-definitions/include/ospf/ospf-distance-per-protocol.xml.i38
-rw-r--r--interface-definitions/include/ospf/ospf-interface-common.xml.i (renamed from interface-definitions/include/ospf-interface-common.xml.i)4
-rw-r--r--interface-definitions/include/ospf/ospf-intervals.xml.i (renamed from interface-definitions/include/ospf-intervals.xml.i)4
-rw-r--r--interface-definitions/include/ospf/ospf-metric-type.xml.i (renamed from interface-definitions/include/ospf-metric-type.xml.i)4
-rw-r--r--interface-definitions/include/ospf/ospf-metric.xml.i (renamed from interface-definitions/include/ospf-metric.xml.i)4
-rw-r--r--interface-definitions/include/ospf/ospf-router-id.xml.i14
-rw-r--r--interface-definitions/include/port-number.xml.i4
-rw-r--r--interface-definitions/include/radius-server-ipv4-ipv6.xml.i26
-rw-r--r--interface-definitions/include/radius-server-ipv4.xml.i4
-rw-r--r--interface-definitions/include/radius-server-key.xml.i4
-rw-r--r--interface-definitions/include/radius-server-port.xml.i4
-rw-r--r--interface-definitions/include/rip-access-list.xml.i4
-rw-r--r--interface-definitions/include/rip-access-list6.xml.i4
-rw-r--r--interface-definitions/include/rip-default-information.xml.i4
-rw-r--r--interface-definitions/include/rip-default-metric.xml.i4
-rw-r--r--interface-definitions/include/rip-interface.xml.i4
-rw-r--r--interface-definitions/include/rip-prefix-list.xml.i4
-rw-r--r--interface-definitions/include/rip-prefix-list6.xml.i4
-rw-r--r--interface-definitions/include/rip-redistribute.xml.i6
-rw-r--r--interface-definitions/include/rip-timers.xml.i4
-rw-r--r--interface-definitions/include/route-map.xml.i (renamed from interface-definitions/include/ospf-route-map.xml.i)4
-rw-r--r--interface-definitions/include/source-address-ipv4-ipv6.xml.i8
-rw-r--r--interface-definitions/include/source-address-ipv4.xml.i4
-rw-r--r--interface-definitions/include/source-interface-ethernet.xml.i4
-rw-r--r--interface-definitions/include/source-interface.xml.i11
-rw-r--r--interface-definitions/include/static-route-blackhole.xml.i4
-rw-r--r--interface-definitions/include/static-route-distance.xml.i4
-rw-r--r--interface-definitions/include/static-route-interface.xml.i4
-rw-r--r--interface-definitions/include/static-route-map.xml.i4
-rw-r--r--interface-definitions/include/static-route-vrf.xml.i4
-rw-r--r--interface-definitions/include/static-route.xml.i19
-rw-r--r--interface-definitions/include/static-route6.xml.i4
-rw-r--r--interface-definitions/include/tunnel-local-remote-ip.xml.i37
-rw-r--r--interface-definitions/include/tunnel-parameters-ip.xml.i46
-rw-r--r--interface-definitions/include/tunnel-remote.xml.i18
-rw-r--r--interface-definitions/include/vif-s.xml.i4
-rw-r--r--interface-definitions/include/vif.xml.i4
-rw-r--r--interface-definitions/include/vni.xml.i12
-rw-r--r--interface-definitions/include/vpn-ipsec-encryption.xml.i4
-rw-r--r--interface-definitions/include/vpn-ipsec-hash.xml.i4
-rw-r--r--interface-definitions/include/webproxy-url-filtering.xml.i4
-rw-r--r--interface-definitions/interfaces-erspan.xml.in7
-rw-r--r--interface-definitions/interfaces-geneve.xml.in47
-rw-r--r--interface-definitions/interfaces-l2tpv3.xml.in35
-rw-r--r--interface-definitions/interfaces-macsec.xml.in8
-rw-r--r--interface-definitions/interfaces-tunnel.xml.in48
-rw-r--r--interface-definitions/interfaces-vxlan.xml.in64
-rw-r--r--interface-definitions/nat66.xml.in19
-rw-r--r--interface-definitions/protocols-bfd.xml.in100
-rw-r--r--interface-definitions/protocols-bgp.xml.in899
-rw-r--r--interface-definitions/protocols-ospf.xml.in799
-rw-r--r--interface-definitions/protocols-ospfv3.xml.in195
-rw-r--r--interface-definitions/protocols-rip.xml.in8
-rw-r--r--interface-definitions/protocols-ripng.xml.in2
-rw-r--r--interface-definitions/protocols-vrf.xml.in34
-rw-r--r--interface-definitions/service_console-server.xml.in11
-rw-r--r--interface-definitions/vrf.xml.in50
-rw-r--r--interface-definitions/vrrp.xml.in9
-rw-r--r--op-mode-definitions/include/bgp-afi-common.xml.i40
-rw-r--r--op-mode-definitions/include/bgp-afi-ipv4-ipv6-common.xml.i243
-rw-r--r--op-mode-definitions/include/bgp-prefix-bestpath-multipath.xml.i20
-rw-r--r--op-mode-definitions/include/vni-tagnode-all.xml.i11
-rw-r--r--op-mode-definitions/include/vni-tagnode.xml.i11
-rw-r--r--op-mode-definitions/include/vtysh-generic-detail.xml.i8
-rw-r--r--op-mode-definitions/ipoe-server.xml.in12
-rw-r--r--op-mode-definitions/nat.xml.in10
-rw-r--r--op-mode-definitions/nat66.xml.in98
-rw-r--r--op-mode-definitions/openconnect.xml.in4
-rw-r--r--op-mode-definitions/pppoe-server.xml.in10
-rw-r--r--op-mode-definitions/show-bgp.xml.in257
-rw-r--r--op-mode-definitions/show-evpn.xml.in46
-rw-r--r--op-mode-definitions/show-ip-bgp.xml.in228
-rw-r--r--op-mode-definitions/show-ipv6-bgp.xml.in203
-rw-r--r--op-mode-definitions/wireguard.xml.in34
-rw-r--r--python/vyos/configsession.py4
-rw-r--r--python/vyos/configverify.py43
-rw-r--r--python/vyos/ethtool.py101
-rw-r--r--python/vyos/ifconfig/__init__.py11
-rw-r--r--python/vyos/ifconfig/bond.py20
-rw-r--r--python/vyos/ifconfig/bridge.py38
-rw-r--r--python/vyos/ifconfig/control.py2
-rw-r--r--python/vyos/ifconfig/dummy.py25
-rwxr-xr-xpython/vyos/ifconfig/erspan.py84
-rw-r--r--python/vyos/ifconfig/ethernet.py19
-rw-r--r--python/vyos/ifconfig/geneve.py56
-rw-r--r--python/vyos/ifconfig/input.py3
-rw-r--r--python/vyos/ifconfig/interface.py84
-rw-r--r--python/vyos/ifconfig/l2tpv3.py55
-rw-r--r--python/vyos/ifconfig/loopback.py20
-rw-r--r--python/vyos/ifconfig/macsec.py36
-rw-r--r--python/vyos/ifconfig/macvlan.py38
-rw-r--r--python/vyos/ifconfig/pppoe.py2
-rw-r--r--python/vyos/ifconfig/tunnel.py287
-rw-r--r--python/vyos/ifconfig/vti.py6
-rw-r--r--python/vyos/ifconfig/vtun.py27
-rw-r--r--python/vyos/ifconfig/vxlan.py98
-rw-r--r--python/vyos/ifconfig/wireguard.py29
-rw-r--r--python/vyos/ifconfig/wireless.py37
-rw-r--r--python/vyos/remote.py195
-rw-r--r--python/vyos/template.py27
-rw-r--r--python/vyos/util.py23
-rw-r--r--smoketest/configs/azure-bgp-gateway435
-rw-r--r--smoketest/configs/bgp-bfd-communities533
-rw-r--r--smoketest/configs/bgp-big-as-cloud4
-rw-r--r--smoketest/configs/bgp-small-internet-exchange270
-rw-r--r--smoketest/configs/tunnel-broker142
-rw-r--r--smoketest/configs/vrf-bgp166
-rw-r--r--smoketest/configs/vrf-ospf145
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py40
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bridge.py6
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_erspan.py74
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_geneve.py44
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_l2tpv3.py6
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_macsec.py34
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_tunnel.py159
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_vxlan.py58
-rwxr-xr-xsmoketest/scripts/cli/test_nat66.py35
-rwxr-xr-xsmoketest/scripts/cli/test_policy.py681
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bfd.py83
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py62
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py81
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospfv3.py63
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_rip.py2
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_static.py54
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcp-server.py1
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcpv6-server.py21
-rwxr-xr-xsmoketest/scripts/cli/test_service_pppoe-server.py3
-rwxr-xr-xsmoketest/scripts/cli/test_vrf.py6
-rwxr-xr-xsrc/completion/list_bgp_peer_groups.sh23
-rwxr-xr-xsrc/conf_mode/interfaces-erspan.py32
-rwxr-xr-xsrc/conf_mode/interfaces-ethernet.py30
-rwxr-xr-xsrc/conf_mode/interfaces-geneve.py12
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py33
-rwxr-xr-xsrc/conf_mode/interfaces-macsec.py10
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py5
-rwxr-xr-xsrc/conf_mode/interfaces-pseudo-ethernet.py12
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py88
-rwxr-xr-xsrc/conf_mode/interfaces-vxlan.py13
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py11
-rwxr-xr-xsrc/conf_mode/nat66.py16
-rwxr-xr-xsrc/conf_mode/protocols_bfd.py230
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py100
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py63
-rwxr-xr-xsrc/conf_mode/protocols_ospfv3.py12
-rwxr-xr-xsrc/conf_mode/protocols_static.py24
-rwxr-xr-xsrc/conf_mode/protocols_vrf.py72
-rwxr-xr-xsrc/conf_mode/service_console-server.py45
-rwxr-xr-xsrc/conf_mode/service_webproxy.py3
-rwxr-xr-xsrc/conf_mode/system_console.py25
-rwxr-xr-xsrc/conf_mode/vrrp.py6
-rw-r--r--src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper32
-rw-r--r--src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup8
-rwxr-xr-xsrc/migration-scripts/interfaces/19-to-2061
-rwxr-xr-xsrc/migration-scripts/nat/4-to-56
-rwxr-xr-xsrc/migration-scripts/nat66/0-to-12
-rwxr-xr-xsrc/migration-scripts/quagga/6-to-764
-rwxr-xr-xsrc/migration-scripts/quagga/8-to-961
-rwxr-xr-xsrc/migration-scripts/vrf/1-to-261
-rwxr-xr-xsrc/op_mode/ppp-server-ctrl.py5
-rwxr-xr-xsrc/op_mode/show_interfaces.py4
-rwxr-xr-xsrc/op_mode/show_nat66_rules.py74
-rwxr-xr-xsrc/op_mode/show_nat66_statistics.py63
-rwxr-xr-xsrc/op_mode/show_nat66_translations.py204
-rwxr-xr-xsrc/op_mode/show_nat_rules.py74
-rwxr-xr-xsrc/op_mode/show_nat_statistics.py2
-rwxr-xr-xsrc/op_mode/vtysh_wrapper.sh4
-rwxr-xr-xsrc/services/vyos-configd43
-rwxr-xr-xsrc/system/on-dhcp-event.sh25
-rw-r--r--src/systemd/dropbear@.service5
-rw-r--r--src/tests/test_util.py4
-rwxr-xr-xsrc/validators/fqdn5
-rwxr-xr-xsrc/validators/interface-name2
316 files changed, 8385 insertions, 4697 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index cc5e2f536..04ca4070d 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -5,8 +5,11 @@
<!--- Provide a general summary of your changes in the Title above -->
## Types of changes
-<!--- What types of changes does your code introduce? Put an 'x' in all the boxes that apply. -->
-<!--- NOTE: Markdown requires no leading or trailing whitespace inside the [ ] for checking the box, please use [x] -->
+<!---
+What types of changes does your code introduce? Put an 'x' in all the boxes that apply.
+NOTE: Markdown requires no leading or trailing whitespace inside the [ ] for checking
+the box, please use [x]
+-->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Code style update (formatting, renaming)
@@ -16,6 +19,7 @@
## Related Task(s)
<!-- All submitted PRs must be linked to a Task on Phabricator. -->
+* https://phabricator.vyos.net/Txxxx
## Component(s) name
<!-- A rather incomplete list of components: ethernet, wireguard, bgp, mpls, ldp, l2tp, dhcp ... -->
@@ -24,8 +28,14 @@
<!--- Describe your changes in detail -->
## How to test
-<!--- Please describe in detail how you tested your changes. -->
-<!--- Include details of your testing environment, and the tests you ran to -->
+<!---
+Please describe in detail how you tested your changes. Include details of your testing
+environment, and the tests you ran. When pasting configs, logs, shell output, backtraces,
+and other large chunks of text, surround this text with triple backtics
+```
+like this
+```
+-->
## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
@@ -33,6 +43,7 @@
<!--- The entire development process is outlined here: https://docs.vyos.io/en/latest/contributing/development.html -->
- [ ] I have read the [**CONTRIBUTING**](https://github.com/vyos/vyos-1x/blob/current/CONTRIBUTING.md) document
- [ ] I have linked this PR to one or more Phabricator Task(s)
+- [ ] I have run the components [**SMOKETESTS**](https://github.com/vyos/vyos-1x/tree/current/smoketest/scripts/cli) if applicable
- [ ] My commit headlines contain a valid Task id
- [ ] My change requires a change to the documentation
- [ ] I have updated the documentation accordingly
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7ac48ee4c..8458d3208 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,6 +8,81 @@ review this contribution guideline.
The following paragraphs are an excerpt from our Documentation.
+## Submit a Patch
+
+Patches are always more than welcome. To have a clean and easy to maintain
+repository we have some guidelines when working with Git. A clean repository
+eases the automatic generation of a changelog file.
+
+A good approach for writing commit messages is actually to have a look at the
+file(s) history by invoking git log path/to/file.txt.
+
+### Prepare patch/commit
+
+In a big system, such as VyOS, that is comprised of multiple components, it’s
+impossible to keep track of all the changes and bugs/feature requests in one’s
+head. We use a bugtracker known as Phabricator for it (“issue tracker” would
+be a better term, but this one stuck).
+
+The information is used in three ways:
+
+* Keep track of the progress (what we have already done in this branch and
+ what we still need to do).
+* Prepare automatic release notes for upcoming releases
+* Help future maintainers of VyOS (it could be you!) to find out why certain
+ things have been changed in the codebase or why certain features have been
+ added
+
+To make this approach work, every change must be associated with a task number
+(prefixed with **T**) and a component. If there is no bug report/feature
+request for the changes you are going to make, you have to create a Phabricator
+task first. Once there is an entry in Phabricator, you should reference its id
+in your commit message, as shown below:
+
+* `ddclient: T1030: auto create runtime directories`
+* `Jenkins: add current Git commit ID to build description`
+
+If there is no [Phabricator](https://phabricator.vyos.net) reference in the
+commits of your pull request, we have to ask you to amend the commit message.
+Otherwise we will have to reject it.
+
+## Writing good commit messages
+
+The format should be and is inspired by this very good and detailed
+[Git documentation](https://git-scm.com/book/ch5-2.html), it is also worth
+reading https://chris.beams.io/posts/git-commit/.
+
+This is nothing VyOS specific - it is more a general topic for distributed
+development environments.
+
+* A single, short, summary of the commit (recommended 50 characters or less,
+ not exceeding 80 characters) containing a prefix of the changed component
+ and the corresponding Phabricator reference e.g. `snmp: T1111:` or
+ `ethernet: T2222:` - multiple components could be concatenated as in `snmp:
+ ethernet: T3333`
+* In some contexts, the first line is treated as the subject of an email and
+ the rest of the text as the body. The blank line separating the summary from
+ the body is critical (unless you omit the body entirely); tools like rebase
+ can get confused if you run the two together.
+* Followed by a message which describes all the details like:
+ * What/why/how something has been changed, makes everyone’s life easier when
+ working with `git bisect`
+ * All text of the commit message should be wrapped at 72 characters if
+ possible which makes reading commit logs easier with git log on a standard
+ terminal (which happens to be 80x25)
+ * If applicable a reference to a previous commit should be made linking those
+ commits nicely when browsing the history: `After commit abcd12ef ("snmp:
+ this is a headline") a Python import statement is missing, throwing the
+ following exception: ABCDEF`
+* Always use the `-x` option to the `git cherry-pick` command when back or
+ forward porting an individual commit. This automatically appends the line:
+ `(cherry picked from commit <ID>)` to the original authors commit message
+ making it easier when bisecting problems.
+* Every change set must be consistent (self containing)! Do not fix multiple
+ bugs in a single commit. If you already worked on multiple fixes in the same
+ file use git add –patch to only add the parts related to the one issue into
+ your upcoming commit.
+
## Bug Report/Issue
Issues or bugs are found in any software project. VyOS is not an exception.
diff --git a/Pipfile b/Pipfile
index 5bb9fb73d..5a4fb6fe9 100644
--- a/Pipfile
+++ b/Pipfile
@@ -12,6 +12,7 @@ coverage = "*"
[packages]
vyos = {file = "./python"}
jinja2 = "*"
+paramiko = "*"
[requires]
python_version = "3.6"
diff --git a/README.md b/README.md
index edc58712e..a090cf0cb 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ The guidelines in a nutshell:
Tests are executed at build time, you can also execute them by hand with:
```
-pipenv install
+pipenv install --dev
pipenv shell
make test
```
diff --git a/data/configd-include.json b/data/configd-include.json
index e50dbf1b2..eed858363 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -32,6 +32,7 @@
"nat66.py",
"ntp.py",
"policy-local-route.py",
+"protocols_bfd.py",
"protocols_bgp.py",
"protocols_igmp.py",
"protocols_isis.py",
@@ -43,7 +44,6 @@
"protocols_ripng.py",
"protocols_static.py",
"protocols_static_multicast.py",
-"protocols_vrf.py",
"salt-minion.py",
"service_console-server.py",
"service_ids_fastnetmon.py",
diff --git a/data/templates/accel-ppp/config_ip_pool.j2 b/data/templates/accel-ppp/config_ip_pool.j2
index 973bc0071..3b0f68084 100644
--- a/data/templates/accel-ppp/config_ip_pool.j2
+++ b/data/templates/accel-ppp/config_ip_pool.j2
@@ -4,7 +4,7 @@
gw-ip-address={{ gateway_address }}
{% endif %}
{% if client_ip_pool.start is defined and client_ip_pool.stop is defined and client_ip_pool.start is not none and client_ip_pool.stop is not none %}
-{{ client_ip_pool.start }}-{{ client_ip_pool.stop }}
+{{ client_ip_pool.start }}-{{ client_ip_pool.stop.split('.')[3] }}
{% endif %}
{% if client_ip_pool.subnet is defined and client_ip_pool.subnet is not none %}
{% for subnet in client_ip_pool.subnet %}
diff --git a/data/templates/accel-ppp/pppoe.config.tmpl b/data/templates/accel-ppp/pppoe.config.tmpl
index 3dfb615da..f444af85c 100644
--- a/data/templates/accel-ppp/pppoe.config.tmpl
+++ b/data/templates/accel-ppp/pppoe.config.tmpl
@@ -96,12 +96,24 @@ mtu={{ mtu }}
verbose=1
ac-name={{ access_concentrator }}
-{% if interface %}
-{% for iface in interface %}
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+{% if iface_config.vlan_id is not defined and iface_config.vlan_range is not defined %}
interface={{ iface }}
-{% if interface[iface].vlan_id is defined or interface[iface].vlan_range is defined %}
-vlan-mon={{ iface }},{{ interface[iface].vlan_id | join(',') }},{{ interface[iface].vlan_range | join(',') }}
-interface=re:{{ interface.name }}\.\d+
+{% endif %}
+{% if iface_config.vlan_id is defined and iface_config.vlan_range is not defined %}
+{% for vlan in iface_config.vlan_id %}
+interface={{ iface }}.{{ vlan }}
+vlan-mon={{ iface }},{{ vlan }}
+{% endfor %}
+{% endif %}
+{% if iface_config.vlan_range is defined and iface_config.vlan_id is not defined %}
+vlan-mon={{ iface }},{{ iface_config.vlan_range | join(',') }}
+interface=re:{{ iface | replace('.', '\\.') }}\.\d+
+{% endif %}
+{% if iface_config.vlan_id is defined and iface_config.vlan_range is defined %}
+vlan-mon={{ iface }},{{ iface_config.vlan_id | join(',') }},{{ iface_config.vlan_range | join(',') }}
+interface=re:{{ iface | replace('.', '\\.') }}\.\d+
{% endif %}
{% endfor %}
{% endif %}
diff --git a/data/templates/conserver/dropbear@.service.tmpl b/data/templates/conserver/dropbear@.service.tmpl
new file mode 100644
index 000000000..4bb73f751
--- /dev/null
+++ b/data/templates/conserver/dropbear@.service.tmpl
@@ -0,0 +1,4 @@
+[Service]
+ExecStart=
+ExecStart=/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -c "/usr/bin/console {{ device }}" -P /run/conserver/dropbear.%I.pid -p %I
+PIDFile=/run/conserver/dropbear.%I.pid
diff --git a/data/templates/dhcp-client/daemon-options.tmpl b/data/templates/dhcp-client/daemon-options.tmpl
index 290aefa49..40629dca1 100644
--- a/data/templates/dhcp-client/daemon-options.tmpl
+++ b/data/templates/dhcp-client/daemon-options.tmpl
@@ -1,4 +1,4 @@
### Autogenerated by interface.py ###
-DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ifname}}.conf -pf /var/lib/dhcp/dhclient_{{ifname}}.pid -lf /var/lib/dhcp/dhclient_{{ifname}}.leases {{ifname}}"
+DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ifname}}.conf -pf /var/lib/dhcp/dhclient_{{ifname}}.pid -lf /var/lib/dhcp/dhclient_{{ifname}}.leases{{" -e IF_METRIC=" ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is defined and dhcp_options.default_route_distance is not none}} {{ifname}}"
diff --git a/data/templates/dhcp-server/dhcpd.conf.tmpl b/data/templates/dhcp-server/dhcpd.conf.tmpl
index ff2e31998..f0bfa468c 100644
--- a/data/templates/dhcp-server/dhcpd.conf.tmpl
+++ b/data/templates/dhcp-server/dhcpd.conf.tmpl
@@ -8,16 +8,12 @@
on release {
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
- set ClientMac = binary-to-ascii(16, 8, ":",substring(hardware, 1, 6));
- set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", ClientName, ClientIp, ClientMac, ClientDomain);
+ execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}
on expiry {
set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
- set ClientMac = binary-to-ascii(16, 8, ":",substring(hardware, 1, 6));
- set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", ClientName, ClientIp, ClientMac, ClientDomain);
+ execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}
{% endif %}
@@ -201,11 +197,15 @@ shared-network {{ network | replace('_','-') }} {
on commit {
set shared-networkname = "{{ network | replace('_','-') }}";
{% if hostfile_update is defined %}
- set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
- set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
+ set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname");
+ if not (ClientName = "empty_hostname") {
+ set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
+ execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
+ } else {
+ log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac));
+ }
{% endif %}
}
}
diff --git a/data/templates/dhcp-server/dhcpdv6.conf.tmpl b/data/templates/dhcp-server/dhcpdv6.conf.tmpl
index de7c9b29c..25e5fa592 100644
--- a/data/templates/dhcp-server/dhcpdv6.conf.tmpl
+++ b/data/templates/dhcp-server/dhcpdv6.conf.tmpl
@@ -8,6 +8,12 @@ log-facility local7;
option dhcp6.preference {{ preference }};
{% endif %}
+{% if global_parameters is defined and global_parameters.name_server is defined and global_parameters.name_server is not none %}
+{% for nameserver in global_parameters.name_server %}
+option dhcp6.name-servers {{ nameserver }};
+{% endfor %}
+{% endif %}
+
# Shared network configration(s)
{% if shared_network_name is defined and shared_network_name is not none %}
{% for network, network_config in shared_network_name.items() if network_config.disable is not defined %}
diff --git a/data/templates/firewall/nftables-nat66.tmpl b/data/templates/firewall/nftables-nat66.tmpl
index b1a8f7a16..e5c1b1b8d 100644
--- a/data/templates/firewall/nftables-nat66.tmpl
+++ b/data/templates/firewall/nftables-nat66.tmpl
@@ -1,9 +1,13 @@
#!/usr/sbin/nft -f
{% macro nptv6_rule(rule,config, chain) %}
-{% set src_prefix = "ip6 saddr " + config.source.prefix if config.source is defined and config.source.prefix is defined and config.source.prefix is not none %}
-{% set dest_address = "ip6 daddr " + config.destination.address if config.destination is defined and config.destination.address is defined and config.destination.address is not none %}
+{% set comment = '' %}
+{% set base_log = '' %}
+{% set src_prefix = "ip6 saddr " + config.source.prefix if config.source is defined and config.source.prefix is defined and config.source.prefix is not none %}
+{% set dest_address = "ip6 daddr " + config.destination.address if config.destination is defined and config.destination.address is defined and config.destination.address is not none %}
{% if chain == "PREROUTING" %}
+{% set comment = "DST-NAT66-" + rule %}
+{% set base_log = '[NAT66-DST-' + rule %}
{% set interface = " iifname \"" + config.inbound_interface + "\"" if config.inbound_interface is defined and config.inbound_interface != 'any' else '' %}
{% if config.translation.address | is_ip_network %}
{# support 1:1 network translation #}
@@ -13,13 +17,29 @@
{% endif %}
{% set trns_address = dnat_type + config.translation.address if config.translation is defined and config.translation.address is defined and config.translation.address is not none %}
{% elif chain == "POSTROUTING" %}
+{% set comment = 'SRC-NAT66-' + rule %}
+{% set base_log = '[NAT66-SRC-' + rule %}
+{% if config.translation is defined and config.translation.address is defined and config.translation.address is not none %}
+{% if config.translation.address == 'masquerade' %}
+{% set trns_address = config.translation.address %}
+{% else %}
+{% if config.translation.address | is_ip_network %}
+{# support 1:1 network translation #}
+{% set snat_type = "snat prefix to " %}
+{% else %}
+{% set snat_type = "snat to " %}
+{% endif %}
+{% set trns_address = snat_type + config.translation.address %}
+{% endif %}
+{% endif %}
{% set interface = " oifname \"" + config.outbound_interface + "\"" if config.outbound_interface is defined else '' %}
-{% set trns_prefix = "snat prefix to " + config.translation.prefix if config.translation is defined and config.translation.prefix is defined and config.translation.prefix is not none %}
{% endif %}
-{% set comment = "NPT-NAT-" + rule %}
-{% if rule.log %}
-{% set base_log = "[NPT-DST-" + rule %}
-{% set log = base_log + "]" %}
+{% if config.log is defined %}
+{% if config.translation is defined and config.translation.address is defined and config.translation.address == 'masquerade' %}
+{% set log = base_log +'-MASQ]' %}
+{% else %}
+{% set log = base_log + "]" %}
+{% endif %}
{% endif %}
{% set output = "add rule ip6 nat " + chain + interface %}
{# Count packets #}
@@ -35,9 +55,6 @@
{% if dest_address %}
{% set output = output + " " + dest_address %}
{% endif %}
-{% if trns_prefix %}
-{% set output = output + " " + trns_prefix %}
-{% endif %}
{% if trns_address %}
{% set output = output + " " + trns_address %}
{% endif %}
diff --git a/data/templates/frr/bfd.frr.tmpl b/data/templates/frr/bfd.frr.tmpl
index 9e5ad3379..16f8be92c 100644
--- a/data/templates/frr/bfd.frr.tmpl
+++ b/data/templates/frr/bfd.frr.tmpl
@@ -1,22 +1,44 @@
!
bfd
-{% for peer in old_peers %}
- no peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %}
-
-{% endfor %}
-!
-{% for peer in new_peers %}
- peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %}
-
- detect-multiplier {{ peer.multiplier }}
- receive-interval {{ peer.rx_interval }}
- transmit-interval {{ peer.tx_interval }}
-{% if peer.echo_mode %}
- echo-mode
+{% if profile is defined and profile is not none %}
+{% for profile_name, profile_config in profile.items() %}
+ profile {{ profile_name }}
+ detect-multiplier {{ profile_config.interval.multiplier }}
+ receive-interval {{ profile_config.interval.receive }}
+ transmit-interval {{ profile_config.interval.transmit }}
+{% if profile_config.interval['echo-interval'] is defined and profile_config.interval['echo-interval'] is not none %}
+ echo-interval {{ profile_config.interval['echo-interval'] }}
+{% endif %}
+{% if profile_config['echo-mode'] is defined %}
+ echo-mode
+{% endif %}
+{% if profile_config.shutdown is defined %}
+ shutdown
+{% else %}
+ no shutdown
+{% endif %}
+ exit
+{% endfor %}
{% endif %}
-{% if peer.echo_interval != '' %}
- echo-interval {{ peer.echo_interval }}
+{% if peer is defined and peer is not none %}
+{% for peer_name, peer_config in peer.items() %}
+ peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source is defined and peer_config.source.address is defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source is defined and peer_config.source.interface is defined }}
+ detect-multiplier {{ peer_config.interval.multiplier }}
+ receive-interval {{ peer_config.interval.receive }}
+ transmit-interval {{ peer_config.interval.transmit }}
+{% if peer_config.interval['echo-interval'] is defined and peer_config.interval['echo-interval'] is not none %}
+ echo-interval {{ peer_config.interval['echo-interval'] }}
+{% endif %}
+{% if peer_config['echo-mode'] is defined %}
+ echo-mode
+{% endif %}
+{% if peer_config.shutdown is defined %}
+ shutdown
+{% else %}
+ no shutdown
+{% endif %}
+ exit
+{% endfor %}
{% endif %}
- {% if not peer.shutdown %}no {% endif %}shutdown
-{% endfor %}
+ end
!
diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl
index bb8131730..30e1ec082 100644
--- a/data/templates/frr/bgp.frr.tmpl
+++ b/data/templates/frr/bgp.frr.tmpl
@@ -9,6 +9,9 @@
{% if config.remote_as is defined and config.remote_as is not none %}
neighbor {{ neighbor }} remote-as {{ config.remote_as }}
{% endif %}
+{% if config.interface is defined and config.interface.remote_as is defined and config.interface.remote_as is not none %}
+ neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }}
+{% endif %}
{% if config.advertisement_interval is defined and config.advertisement_interval is not none %}
neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }}
{% endif %}
@@ -58,6 +61,14 @@
{% if config.ttl_security is defined and config.ttl_security.hops is defined and config.ttl_security.hops is not none %}
neighbor {{ neighbor }} ttl-security hops {{ config.ttl_security.hops }}
{% endif %}
+{% if config.timers is defined %}
+{% if config.timers.connect is defined and config.timers.connect is not none %}
+ neighbor {{ neighbor }} timers connect {{ config.timers.connect }}
+{% endif %}
+{% if config.timers.holdtime is defined and config.timers.keepalive is defined and config.timers.holdtime is not none and config.timers.keepalive is not none %}
+ neighbor {{ neighbor }} timers {{ config.timers.keepalive }} {{ config.timers.holdtime }}
+{% endif %}
+{% endif %}
{% if config.update_source is defined and config.update_source is not none %}
neighbor {{ neighbor }} update-source {{ config.update_source }}
{% endif %}
@@ -65,9 +76,6 @@
{% if config.interface.peer_group is defined and config.interface.peer_group is not none %}
neighbor {{ neighbor }} interface peer-group {{ config.interface.peer_group }}
{% endif %}
-{% if config.interface.remote_as is defined and config.interface.remote_as is not none %}
- neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }}
-{% endif %}
{% if config.interface.v6only is defined and config.interface.v6only is not none %}
{% if config.interface.v6only.peer_group is defined and config.interface.v6only.peer_group is not none %}
neighbor {{ neighbor }} interface v6only peer-group {{ config.interface.v6only.peer_group }}
@@ -108,8 +116,11 @@
{% if afi_config.attribute_unchanged is defined and afi_config.attribute_unchanged is not none %}
neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is defined }}
{% endif %}
-{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list is not none %}
- neighbor {{ neighbor }} capability orf prefix-list {{ afi_config.capability.orf.prefix_list }}
+{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.send is defined %}
+ neighbor {{ neighbor }} capability orf prefix-list send
+{% endif %}
+{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.receive is defined %}
+ neighbor {{ neighbor }} capability orf prefix-list receive
{% endif %}
{% if afi_config.default_originate is defined %}
neighbor {{ neighbor }} default-originate {{ 'route-map ' + afi_config.default_originate.route_map if afi_config.default_originate.route_map is defined }}
@@ -174,10 +185,14 @@
{% endif %}
{% endmacro %}
!
-router bgp {{ asn }}
-{# Disable eBGP policy by default until there is a CLI option #}
-{# https://phabricator.vyos.net/T3183 & https://phabricator.vyos.net/T2100 #}
+router bgp {{ asn }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
+{% if parameters is defined and parameters.ebgp_requires_policy is defined %}
+ bgp ebgp-requires-policy
+{% else %}
no bgp ebgp-requires-policy
+{% endif %}
+{# Workaround for T2100 until we have decided about a migration script #}
+ no bgp network import-check
{% if address_family is defined and address_family is not none %}
{% for afi, afi_config in address_family.items() %}
!
@@ -193,6 +208,12 @@ router bgp {{ asn }}
aggregate-address {{ ip }}{{ ' as-set' if afi_config.aggregate_address[ip].as_set is defined }}{{ ' summary-only' if afi_config.aggregate_address[ip].summary_only is defined }}
{% endfor %}
{% endif %}
+{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ebgp is defined and afi_config.maximum_paths.ebgp is not none %}
+ maximum-paths {{ afi_config.maximum_paths.ebgp }}
+{% endif %}
+{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ibgp is defined and afi_config.maximum_paths.ibgp is not none %}
+ maximum-paths ibgp {{ afi_config.maximum_paths.ibgp }}
+{% endif %}
{% if afi_config.redistribute is defined and afi_config.redistribute is not none %}
{% for protocol in afi_config.redistribute %}
{% if protocol == 'table' %}
@@ -259,6 +280,20 @@ router bgp {{ asn }}
{% if vni_config.advertise_svi_ip is defined %}
advertise-svi-ip
{% endif %}
+{% if vni_config.rd is defined and vni_config.rd is not none %}
+ rd {{ vni_config.rd }}
+{% endif %}
+{% if vni_config.route_target is defined and vni_config.route_target is not none %}
+{% if vni_config.route_target.both is defined and vni_config.route_target.both is not none %}
+ route-target both {{ vni_config.route_target.both }}
+{% endif %}
+{% if vni_config.route_target.export is defined and vni_config.route_target.export is not none %}
+ route-target export {{ vni_config.route_target.export }}
+{% endif %}
+{% if vni_config.route_target.import is defined and vni_config.route_target.import is not none %}
+ route-target import {{ vni_config.route_target.import }}
+{% endif %}
+{% endif %}
exit-vni
{% endfor %}
{% endif %}
@@ -266,25 +301,6 @@ router bgp {{ asn }}
{% endfor %}
{% endif %}
!
-{# set protocols bgp xxxx maximum-paths ibgp x, Generated by default for afi_4 #}
-{# We don't have this parameter in afi_6. But this is supported in FRR #}
-{% if maximum_paths is defined and maximum_paths is not none %}
-{% if maximum_paths.ebgp is defined and maximum_paths.ebgp is not none %}
- !
- address-family ipv4 unicast
- maximum-paths {{ maximum_paths.ebgp }}
- exit-address-family
- !
-{% endif %}
-{% if maximum_paths.ibgp is defined and maximum_paths.ibgp is not none %}
- !
- address-family ipv4 unicast
- maximum-paths ibgp {{ maximum_paths.ibgp }}
- exit-address-family
- !
-{% endif %}
-{% endif %}
- !
{% if peer_group is defined and peer_group is not none %}
{% for peer, config in peer_group.items() %}
{{ bgp_neighbor(peer, config, true) }}
diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospf.frr.tmpl
index 7ca69eee6..a47c64c89 100644
--- a/data/templates/frr/ospf.frr.tmpl
+++ b/data/templates/frr/ospf.frr.tmpl
@@ -1,7 +1,7 @@
!
{% if interface is defined and interface is not none %}
{% for iface, iface_config in interface.items() %}
-interface {{ iface }}
+interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
{% if iface_config.authentication is defined and iface_config.authentication is not none %}
{% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %}
ip ospf authentication-key {{ iface_config.authentication.plaintext_password }}
@@ -50,7 +50,7 @@ interface {{ iface }}
{% endfor %}
{% endif %}
!
-router ospf
+router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
{% if access_list is defined and access_list is not none %}
{% for acl, acl_config in access_list.items() %}
{% for protocol in acl_config.export if acl_config.export is defined %}
@@ -159,6 +159,9 @@ router ospf
passive-interface {{ interface }}
{% endfor %}
{% for interface in passive_interface_exclude if passive_interface_exclude is defined %}
+{% if interface.startswith('vlink') %}
+{% set interface = interface.upper() %}
+{% endif %}
no passive-interface {{ interface }}
{% endfor %}
{% if redistribute is defined and redistribute is not none %}
diff --git a/data/templates/frr/ospfv3.frr.tmpl b/data/templates/frr/ospfv3.frr.tmpl
index c63ef80dc..d08972a80 100644
--- a/data/templates/frr/ospfv3.frr.tmpl
+++ b/data/templates/frr/ospfv3.frr.tmpl
@@ -1,4 +1,47 @@
!
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+{% if iface_config.cost is defined and iface_config.cost is not none %}
+ ipv6 ospf6 cost {{ iface_config.cost }}
+{% endif %}
+{% if iface_config.priority is defined and iface_config.priority is not none %}
+ ipv6 ospf6 priority {{ iface_config.priority }}
+{% endif %}
+{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %}
+ ipv6 ospf6 hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %}
+ ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }}
+{% endif %}
+{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %}
+ ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }}
+{% endif %}
+{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %}
+ ipv6 ospf6 dead-interval {{ iface_config.dead_interval }}
+{% endif %}
+{% if iface_config.bfd is defined %}
+ ipv6 ospf6 bfd
+{% endif %}
+{% if iface_config.mtu_ignore is defined %}
+ ipv6 ospf6 mtu-ignore
+{% endif %}
+{% if iface_config.ifmtu is defined and iface_config.ifmtu is not none %}
+ ipv6 ospf6 ifmtu {{ iface_config.ifmtu }}
+{% endif %}
+{% if iface_config.network is defined and iface_config.network is not none %}
+ ipv6 ospf6 network {{ iface_config.network }}
+{% endif %}
+{% if iface_config.instance_id is defined and iface_config.instance_id is not none %}
+ ipv6 ospf6 instance-id {{ iface_config.instance_id }}
+{% endif %}
+{% if iface_config.passive is defined %}
+ ipv6 ospf6 passive
+{% endif %}
+!
+{% endfor %}
+{% endif %}
+!
router ospf6
{% if area is defined and area is not none %}
{% for area_id, area_config in area.items() %}
diff --git a/data/templates/frr/rpki.frr.tmpl b/data/templates/frr/rpki.frr.tmpl
index 346a0caa9..fbdfa27c3 100644
--- a/data/templates/frr/rpki.frr.tmpl
+++ b/data/templates/frr/rpki.frr.tmpl
@@ -5,9 +5,9 @@ rpki
{% for peer, peer_config in cache.items() %}
{# port is mandatory and preference uses a default value #}
{% if peer_config.ssh is defined and peer_config.ssh.username is defined and peer_config.ssh.username is not none %}
- rpki cache {{ peer }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} {{ peer_config.ssh.known_hosts_file }} preference {{ peer_config.preference }}
+ rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} {{ peer_config.ssh.known_hosts_file }} preference {{ peer_config.preference }}
{% else %}
- rpki cache {{ peer }} {{ peer_config.port }} preference {{ peer_config.preference }}
+ rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} preference {{ peer_config.preference }}
{% endif %}
{% endfor %}
{% endif %}
diff --git a/data/templates/frr/static.frr.tmpl b/data/templates/frr/static.frr.tmpl
index bb0ec80a5..db59a44c2 100644
--- a/data/templates/frr/static.frr.tmpl
+++ b/data/templates/frr/static.frr.tmpl
@@ -1,18 +1,29 @@
{% from 'frr/static_routes_macro.j2' import static_routes %}
!
+{% set ip_prefix = 'ip' %}
+{% set ipv6_prefix = 'ipv6' %}
+{% if vrf is defined and vrf is not none %}
+{# We need to add an additional whitespace in front of the prefix #}
+{# when VRFs are in use, thus we use a variable for prefix handling #}
+{% set ip_prefix = ' ip' %}
+{% set ipv6_prefix = ' ipv6' %}
+vrf {{ vrf }}
+{% endif %}
{# IPv4 routing #}
{% if route is defined and route is not none %}
{% for prefix, prefix_config in route.items() %}
-{{ static_routes('ip', prefix, prefix_config) }}
+{{ static_routes(ip_prefix, prefix, prefix_config) }}
{%- endfor -%}
{% endif %}
-!
{# IPv6 routing #}
{% if route6 is defined and route6 is not none %}
{% for prefix, prefix_config in route6.items() %}
-{{ static_routes('ipv6', prefix, prefix_config) }}
+{{ static_routes(ipv6_prefix, prefix, prefix_config) }}
{%- endfor -%}
{% endif %}
+{% if vrf is defined and vrf is not none %}
+ exit-vrf
+{% endif %}
!
{# Policy route tables #}
{% if table is defined and table is not none %}
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
index b24232ef3..f10b58047 100644
--- a/data/templates/frr/static_routes_macro.j2
+++ b/data/templates/frr/static_routes_macro.j2
@@ -2,6 +2,12 @@
{% if prefix_config.blackhole is defined %}
{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }}
{% endif %}
+{% 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 }}
+{% endif %}
+{% endif %}
{% if prefix_config.interface is defined and prefix_config.interface is not none %}
{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }}
diff --git a/data/templates/frr/vrf.frr.tmpl b/data/templates/frr/vrf.frr.tmpl
deleted file mode 100644
index 0c8726908..000000000
--- a/data/templates/frr/vrf.frr.tmpl
+++ /dev/null
@@ -1,22 +0,0 @@
-{% from 'frr/static_routes_macro.j2' import static_routes %}
-!
-{% if vrf is defined and vrf is not none %}
-{% for vrf_name, vrf_config in vrf.items() %}
-vrf {{ vrf_name }}
-{% if vrf_config.static is defined and vrf_config.static is not none %}
-{# IPv4 routes #}
-{% if vrf_config.static.route is defined and vrf_config.static.route is not none %}
-{% for prefix, prefix_config in vrf_config.static.route.items() %}
- {{ static_routes('ip', prefix, prefix_config) }}
-{%- endfor -%}
-{% endif %}
-{# IPv6 routes #}
-{% if vrf_config.static.route6 is defined and vrf_config.static.route6 is not none %}
-{% for prefix, prefix_config in vrf_config.static.route6.items() %}
- {{ static_routes('ipv6', prefix, prefix_config) }}
-{%- endfor -%}
-{% endif %}
-{% endif %}
-{% endfor %}
-{% endif %}
-!
diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.tmpl
index 855ebff4f..81f8b3b8c 100644
--- a/data/templates/https/nginx.default.tmpl
+++ b/data/templates/https/nginx.default.tmpl
@@ -50,6 +50,7 @@ server {
{% endif %}
}
+ error_page 497 =301 https://$host:{{ server.port }}$request_uri;
error_page 501 502 503 =200 @50*_json;
{% if api_set %}
diff --git a/data/templates/syslog/rsyslog.conf.tmpl b/data/templates/syslog/rsyslog.conf.tmpl
index 10fbb9d3c..e25ef48d4 100644
--- a/data/templates/syslog/rsyslog.conf.tmpl
+++ b/data/templates/syslog/rsyslog.conf.tmpl
@@ -2,47 +2,47 @@
## file based logging
{% if files['global']['marker'] %}
$ModLoad immark
-{% if files['global']['marker-interval'] %}
+{% if files['global']['marker-interval'] %}
$MarkMessagePeriod {{files['global']['marker-interval']}}
-{% endif %}
+{% endif %}
{% endif %}
{% if files['global']['preserver_fqdn'] %}
$PreserveFQDN on
{% endif %}
-{% for file in files %}
-$outchannel {{file}},{{files[file]['log-file']}},{{files[file]['max-size']}},{{files[file]['action-on-max-size']}}
-{{files[file]['selectors']}} :omfile:${{file}}
+{% for file, file_options in files.items() %}
+$outchannel {{ file }},{{ file_options['log-file'] }},{{ file_options['max-size'] }},{{ file_options['action-on-max-size'] }}
+{{ file_options['selectors'] }} :omfile:${{ file }}
{% endfor %}
-{% if console %}
+{% if console is defined and console is not none %}
## console logging
-{% for con in console %}
-{{console[con]['selectors']}} /dev/console
-{% endfor %}
+{% for con, con_options in console.items() %}
+{{ con_options['selectors'] }} /dev/console
+{% endfor %}
{% endif %}
-{% if hosts %}
+{% if hosts is defined and hosts is not none %}
## remote logging
-{% for host in hosts %}
-{% if hosts[host]['proto'] == 'tcp' %}
-{% if hosts[host]['port'] %}
-{% if hosts[host]['oct_count'] %}
-{{hosts[host]['selectors']}} @@(o){{host}}:{{hosts[host]['port']}};RSYSLOG_SyslogProtocol23Format
+{% for host, host_options in hosts.items() %}
+{% if host_options.proto == 'tcp' %}
+{% if host_options.port is defined %}
+{% if host_options.oct_count is defined %}
+{{ host_options.selectors }} @@(o){{ host }}:{{ host_options.port }};RSYSLOG_SyslogProtocol23Format
+{% else %}
+{{ host_options.selectors }} @@{{ host }}:{{ host_options.port }}
+{% endif %}
{% else %}
-{{hosts[host]['selectors']}} @@{{host}}:{{hosts[host]['port']}}
+{{ host_options.selectors }} @@{{ host }}
{% endif %}
{% else %}
-{{hosts[host]['selectors']}} @@{{host}}
-{% endif %}
-{% else %}
-{% if hosts[host]['port'] %}
-{{hosts[host]['selectors']}} @{{host}}:{{hosts[host]['port']}}
-{% else %}
-{{hosts[host]['selectors']}} @{{host}}
+{% if host_options['port'] %}
+{{ host_options.selectors }} @{{ host | bracketize_ipv6 }}:{{ host_options.port }}
+{% else %}
+{{ host_options.selectors }} @{{ host | bracketize_ipv6 }}
+{% endif %}
{% endif %}
-{% endif %}
-{% endfor %}
+{% endfor %}
{% endif %}
-{% if user %}
-{% for u in user %}
-{{user[u]['selectors']}} :omusrmsg:{{u}}
-{% endfor %}
+{% if user is defined and user is not none %}
+{% for username, user_options in user.items() %}
+{{ user_options.selectors }} :omusrmsg:{{ username }}
+{% endfor %}
{% endif %}
diff --git a/debian/changelog b/debian/changelog
index 2b65b22c6..c9d925253 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-vyos-1x (1.3dev0) unstable; urgency=medium
+vyos-1x (1.4dev0) unstable; urgency=medium
* Dummy changelog entry for vyos-1x repository
This is a internal VyOS package and the VyOS package process does not use
@@ -7,4 +7,4 @@ vyos-1x (1.3dev0) unstable; urgency=medium
The correct verion number of this package is auto-generated by GIT
on build-time
- -- VyOS maintainers and contributors <maintainers@vyos.io> Wed, 26 Aug 2020 19:07:24 +0000
+ -- VyOS maintainers and contributors <maintainers@vyos.io> Mon, 11 Jan 2021 19:02:53 +0100
diff --git a/debian/control b/debian/control
index 2c8ee3d43..91ff51b89 100644
--- a/debian/control
+++ b/debian/control
@@ -97,6 +97,7 @@ Depends:
python3-jmespath,
python3-netaddr,
python3-netifaces,
+ python3-paramiko,
python3-psutil,
python3-pystache,
python3-pyudev,
diff --git a/interface-definitions/dhcpv6-server.xml.in b/interface-definitions/dhcpv6-server.xml.in
index fb0e79c47..a3cca06da 100644
--- a/interface-definitions/dhcpv6-server.xml.in
+++ b/interface-definitions/dhcpv6-server.xml.in
@@ -10,6 +10,26 @@
</properties>
<children>
#include <include/generic-disable-node.xml.i>
+ <node name="global-parameters">
+ <properties>
+ <help>Additional global parameters for DHCPv6 server</help>
+ </properties>
+ <children>
+ <leafNode name="name-server">
+ <properties>
+ <help>IPv6 address of a Recursive DNS Server</help>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address of DNS name server</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
<leafNode name="preference">
<properties>
<help>Preference of this DHCPv6 server compared with others</help>
diff --git a/interface-definitions/dns-domain-name.xml.in b/interface-definitions/dns-domain-name.xml.in
index 3b5843b53..ff632e1d1 100644
--- a/interface-definitions/dns-domain-name.xml.in
+++ b/interface-definitions/dns-domain-name.xml.in
@@ -44,7 +44,7 @@
<properties>
<help>System domain name</help>
<constraint>
- <regex>[A-Za-z0-9][-.A-Za-z0-9]*</regex>
+ <validator name="fqdn"/>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/accel-auth-local-users.xml.i b/interface-definitions/include/accel-auth-local-users.xml.i
index 35c7a2a06..70a08c10e 100644
--- a/interface-definitions/include/accel-auth-local-users.xml.i
+++ b/interface-definitions/include/accel-auth-local-users.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-auth-local-users.xml.i -->
+<!-- include start from accel-auth-local-users.xml.i -->
<node name="local-users">
<properties>
<help>Local user authentication for PPPoE server</help>
@@ -48,4 +48,4 @@
</tagNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-auth-mode.xml.i b/interface-definitions/include/accel-auth-mode.xml.i
index 85c3c5e82..81d687182 100644
--- a/interface-definitions/include/accel-auth-mode.xml.i
+++ b/interface-definitions/include/accel-auth-mode.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-auth-mode.xml.i -->
+<!-- include start from accel-auth-mode.xml.i -->
<leafNode name="mode">
<properties>
<help>Authentication mode used by this server</help>
@@ -19,4 +19,4 @@
</properties>
<defaultValue>local</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-auth-protocols.xml.i b/interface-definitions/include/accel-auth-protocols.xml.i
index a6899a4d8..c5cf743c6 100644
--- a/interface-definitions/include/accel-auth-protocols.xml.i
+++ b/interface-definitions/include/accel-auth-protocols.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-auth-protocols.xml.i -->
+<!-- include start from accel-auth-protocols.xml.i -->
<leafNode name="protocols">
<properties>
<help>Authentication protocol for remote access peer SSTP VPN</help>
@@ -28,4 +28,4 @@
</properties>
<defaultValue>pap chap mschap mschap-v2</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-client-ip-pool-start-stop.xml.i b/interface-definitions/include/accel-client-ip-pool-start-stop.xml.i
index b578f2b2c..b0668f93f 100644
--- a/interface-definitions/include/accel-client-ip-pool-start-stop.xml.i
+++ b/interface-definitions/include/accel-client-ip-pool-start-stop.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-client-ip-pool-start-stop.xml.i -->
+<!-- include start from accel-client-ip-pool-start-stop.xml.i -->
<leafNode name="start">
<properties>
<help>First IP address in the pool</help>
@@ -15,4 +15,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-client-ip-pool-subnet.xml.i b/interface-definitions/include/accel-client-ip-pool-subnet.xml.i
index 8e9ca0e92..72f660c39 100644
--- a/interface-definitions/include/accel-client-ip-pool-subnet.xml.i
+++ b/interface-definitions/include/accel-client-ip-pool-subnet.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-client-ip-pool-subnet.xml.i -->
+<!-- include start from accel-client-ip-pool-subnet.xml.i -->
<leafNode name="subnet">
<properties>
<help>Client IP subnet (CIDR notation)</help>
@@ -13,4 +13,4 @@
<multi />
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-client-ipv6-pool.xml.i b/interface-definitions/include/accel-client-ipv6-pool.xml.i
index d15ff35d4..3608c2a0b 100644
--- a/interface-definitions/include/accel-client-ipv6-pool.xml.i
+++ b/interface-definitions/include/accel-client-ipv6-pool.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-client-ipv6-pool.xml.i -->
+<!-- include start from accel-client-ipv6-pool.xml.i -->
<node name="client-ipv6-pool">
<properties>
<help>Pool of client IPv6 addresses</help>
@@ -58,4 +58,4 @@
</tagNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-gateway-address.xml.i b/interface-definitions/include/accel-gateway-address.xml.i
index c45c8b532..f7f9c721d 100644
--- a/interface-definitions/include/accel-gateway-address.xml.i
+++ b/interface-definitions/include/accel-gateway-address.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-gateway-address.xml.i -->
+<!-- include start from accel-gateway-address.xml.i -->
<leafNode name="gateway-address">
<properties>
<help>Gateway IP address</help>
@@ -12,4 +12,4 @@
</valueHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-lcp-echo-interval-failure.xml.i b/interface-definitions/include/accel-lcp-echo-interval-failure.xml.i
index cccf4b4f2..26f010916 100644
--- a/interface-definitions/include/accel-lcp-echo-interval-failure.xml.i
+++ b/interface-definitions/include/accel-lcp-echo-interval-failure.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-lcp-echo-interval-failure.xml.i -->
+<!-- include start from accel-lcp-echo-interval-failure.xml.i -->
<leafNode name="lcp-echo-interval">
<properties>
<help>LCP echo-requests/sec</help>
@@ -17,4 +17,4 @@
</properties>
<defaultValue>3</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-lcp-echo-timeout.xml.i b/interface-definitions/include/accel-lcp-echo-timeout.xml.i
index 888fa9d41..a60ca7ace 100644
--- a/interface-definitions/include/accel-lcp-echo-timeout.xml.i
+++ b/interface-definitions/include/accel-lcp-echo-timeout.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-lcp-echo-timeout.xml.i -->
+<!-- include start from accel-lcp-echo-timeout.xml.i -->
<leafNode name="lcp-echo-timeout">
<properties>
<help>Timeout in seconds to wait for any peer activity. If this option specified it turns on adaptive lcp echo functionality and "lcp-echo-failure" is not used.</help>
@@ -8,4 +8,4 @@
</properties>
<defaultValue>0</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-mtu-128-16384.xml.i b/interface-definitions/include/accel-mtu-128-16384.xml.i
index 6bd089823..c9cac8e45 100644
--- a/interface-definitions/include/accel-mtu-128-16384.xml.i
+++ b/interface-definitions/include/accel-mtu-128-16384.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-mtu-128-16384.xml.i -->
+<!-- include start from accel-mtu-128-16384.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU) - default 1492</help>
@@ -8,4 +8,4 @@
</properties>
<defaultValue>1492</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-name-server.xml.i b/interface-definitions/include/accel-name-server.xml.i
index e46c75b52..68e4ae418 100644
--- a/interface-definitions/include/accel-name-server.xml.i
+++ b/interface-definitions/include/accel-name-server.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-name-server.xml.i -->
+<!-- include start from accel-name-server.xml.i -->
<leafNode name="name-server">
<properties>
<help>Domain Name Server (DNS) propagated to client</help>
@@ -17,4 +17,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-ppp-mppe.xml.i b/interface-definitions/include/accel-ppp-mppe.xml.i
index b7f9cfd92..dbf231ebe 100644
--- a/interface-definitions/include/accel-ppp-mppe.xml.i
+++ b/interface-definitions/include/accel-ppp-mppe.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-ppp-mppe.xml.i -->
+<!-- include start from accel-ppp-mppe.xml.i -->
<leafNode name="mppe">
<properties>
<help>Specifies mppe negotiation preferences</help>
@@ -23,4 +23,4 @@
</properties>
<defaultValue>prefer</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-radius-additions-disable-accounting.xml.i b/interface-definitions/include/accel-radius-additions-disable-accounting.xml.i
index dc5b9dd96..209f7a5f8 100644
--- a/interface-definitions/include/accel-radius-additions-disable-accounting.xml.i
+++ b/interface-definitions/include/accel-radius-additions-disable-accounting.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from accel-radius-additions-disable-accounting.xml.i -->
+<!-- include start from accel-radius-additions-disable-accounting.xml.i -->
<leafNode name="disable-accounting">
<properties>
<help>Disable accounting</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-radius-additions-rate-limit.xml.i b/interface-definitions/include/accel-radius-additions-rate-limit.xml.i
index 23a4a51cf..8c37c62d1 100644
--- a/interface-definitions/include/accel-radius-additions-rate-limit.xml.i
+++ b/interface-definitions/include/accel-radius-additions-rate-limit.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-radius-additions-rate-limit.xml.i -->
+<!-- include start from accel-radius-additions-rate-limit.xml.i -->
<node name="rate-limit">
<properties>
<help>Upload/Download speed limits</help>
@@ -23,4 +23,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-radius-additions.xml.i b/interface-definitions/include/accel-radius-additions.xml.i
index 0067b6d1c..3df0f88fa 100644
--- a/interface-definitions/include/accel-radius-additions.xml.i
+++ b/interface-definitions/include/accel-radius-additions.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-radius-additions.xml.i -->
+<!-- include start from accel-radius-additions.xml.i -->
<node name="radius">
<children>
<leafNode name="acct-interim-jitter">
@@ -150,4 +150,4 @@
</node>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/accel-wins-server.xml.i b/interface-definitions/include/accel-wins-server.xml.i
index 6de032981..6d5d3d301 100644
--- a/interface-definitions/include/accel-wins-server.xml.i
+++ b/interface-definitions/include/accel-wins-server.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from accel-wins-server.xml.i -->
+<!-- include start from accel-wins-server.xml.i -->
<leafNode name="wins-server">
<properties>
<help>Windows Internet Name Service (WINS) servers propagated to client</help>
@@ -12,4 +12,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/address-ipv4-ipv6-dhcp.xml.i b/interface-definitions/include/address-ipv4-ipv6-dhcp.xml.i
index 7805110bc..b9dd59bea 100644
--- a/interface-definitions/include/address-ipv4-ipv6-dhcp.xml.i
+++ b/interface-definitions/include/address-ipv4-ipv6-dhcp.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from address-ipv4-ipv6-dhcp.xml.i -->
+<!-- include start from address-ipv4-ipv6-dhcp.xml.i -->
<leafNode name="address">
<properties>
<help>IP address</help>
@@ -28,4 +28,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/address-ipv4-ipv6.xml.i b/interface-definitions/include/address-ipv4-ipv6.xml.i
index b11610104..519622050 100644
--- a/interface-definitions/include/address-ipv4-ipv6.xml.i
+++ b/interface-definitions/include/address-ipv4-ipv6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from address-ipv4-ipv6.xml.i -->
+<!-- include start from address-ipv4-ipv6.xml.i -->
<leafNode name="address">
<properties>
<help>IP address</help>
@@ -16,4 +16,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bfd-common.xml.i b/interface-definitions/include/bfd-common.xml.i
new file mode 100644
index 000000000..b47b47612
--- /dev/null
+++ b/interface-definitions/include/bfd-common.xml.i
@@ -0,0 +1,72 @@
+<!-- include start from bfd-common.xml.i -->
+<leafNode name="echo-mode">
+ <properties>
+ <help>Enables the echo transmission mode</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<node name="interval">
+ <properties>
+ <help>Configure timer intervals</help>
+ </properties>
+ <children>
+ <leafNode name="receive">
+ <properties>
+ <help>Minimum interval of receiving control packets</help>
+ <valueHelp>
+ <format>10-60000</format>
+ <description>Interval in milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 10-60000"/>
+ </constraint>
+ </properties>
+ <defaultValue>300</defaultValue>
+ </leafNode>
+ <leafNode name="transmit">
+ <properties>
+ <help>Minimum interval of transmitting control packets</help>
+ <valueHelp>
+ <format>10-60000</format>
+ <description>Interval in milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 10-60000"/>
+ </constraint>
+ </properties>
+ <defaultValue>300</defaultValue>
+ </leafNode>
+ <leafNode name="multiplier">
+ <properties>
+ <help>Multiplier to determine packet loss</help>
+ <valueHelp>
+ <format>2-255</format>
+ <description>Remote transmission interval will be multiplied by this value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 2-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>3</defaultValue>
+ </leafNode>
+ <leafNode name="echo-interval">
+ <properties>
+ <help>Echo receive transmission interval</help>
+ <valueHelp>
+ <format>10-60000</format>
+ <description>The minimal echo receive transmission interval that this system is capable of handling</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 10-60000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<leafNode name="shutdown">
+ <properties>
+ <help>Disable this peer</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-l2vpn-common.xml.i b/interface-definitions/include/bgp-afi-l2vpn-common.xml.i
deleted file mode 100644
index 11b1cf6bf..000000000
--- a/interface-definitions/include/bgp-afi-l2vpn-common.xml.i
+++ /dev/null
@@ -1,14 +0,0 @@
-<!-- included start from bgp-afi-l2vpn-common.xml.i -->
-<leafNode name="advertise-default-gw">
- <properties>
- <help>Advertise All default g/w mac-ip routes in EVPN</help>
- <valueless/>
- </properties>
-</leafNode>
-<leafNode name="advertise-svi-ip">
- <properties>
- <help>Advertise svi mac-ip routes in EVPN</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-afi-peer-group.xml.i b/interface-definitions/include/bgp-afi-peer-group.xml.i
deleted file mode 100644
index c98a91030..000000000
--- a/interface-definitions/include/bgp-afi-peer-group.xml.i
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- included start from bgp-afi-peer-group.xml.i -->
-<leafNode name="peer-group">
- <properties>
- <help>Peer group used for this neighbor</help>
- </properties>
-</leafNode>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i b/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i
deleted file mode 100644
index aea10c20c..000000000
--- a/interface-definitions/include/bgp-neighbor-afi-ipv6-unicast.xml.i
+++ /dev/null
@@ -1,21 +0,0 @@
-<!-- included start from bgp-neighbor-afi-ipv6-unicast.xml.i -->
-<node name="ipv6-unicast">
- <properties>
- <help>IPv6 BGP neighbor parameters</help>
- </properties>
- <children>
- <node name="capability">
- <properties>
- <help>Advertise capabilities to this neighbor (IPv6)</help>
- </properties>
- <children>
- #include <include/bgp-afi-capability-orf.xml.i>
- </children>
- </node>
- #include <include/bgp-afi-peer-group.xml.i>
- #include <include/bgp-afi-ipv6-nexthop-local.xml.i>
- #include <include/bgp-afi-ipv6-prefix-list.xml.i>
- #include <include/bgp-afi-common.xml.i>
- </children>
-</node>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-neighbor-afi-l2vpn-evpn.xml.i b/interface-definitions/include/bgp-neighbor-afi-l2vpn-evpn.xml.i
deleted file mode 100644
index df346afc1..000000000
--- a/interface-definitions/include/bgp-neighbor-afi-l2vpn-evpn.xml.i
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- included start from bgp-neighbor-afi-l2vpn-evpn.xml.i -->
-<node name="l2vpn-evpn">
- <properties>
- <help>L2VPN EVPN BGP settings</help>
- </properties>
- <children>
- #include <include/bgp-afi-allowas-in.xml.i>
- #include <include/bgp-afi-attribute-unchanged.xml.i>
- #include <include/bgp-afi-nexthop-self.xml.i>
- #include <include/bgp-afi-route-map.xml.i>
- #include <include/bgp-afi-route-reflector-client.xml.i>
- #include <include/bgp-afi-route-server-client.xml.i>
- #include <include/bgp-afi-soft-reconfiguration.xml.i>
- </children>
-</node>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-route-map.xml.i b/interface-definitions/include/bgp-route-map.xml.i
deleted file mode 100644
index 18b092354..000000000
--- a/interface-definitions/include/bgp-route-map.xml.i
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- included start from bgp-route-map.xml.i -->
-<leafNode name="route-map">
- <properties>
- <help>Route-map to modify route attributes</help>
- <completionHelp>
- <path>policy route-map</path>
- </completionHelp>
- </properties>
-</leafNode>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-shutdown.xml.i b/interface-definitions/include/bgp-shutdown.xml.i
deleted file mode 100644
index 330120bba..000000000
--- a/interface-definitions/include/bgp-shutdown.xml.i
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- included start from bgp-shutdown.xml.i -->
-<leafNode name="shutdown">
- <properties>
- <help>Administratively shut down peer-group</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- included end -->
diff --git a/interface-definitions/include/bgp-afi-aggregate-address.xml.i b/interface-definitions/include/bgp/bgp-afi-aggregate-address.xml.i
index c33d1097c..c731e970b 100644
--- a/interface-definitions/include/bgp-afi-aggregate-address.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-aggregate-address.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-aggregate-address.xml.i -->
+<!-- include start from bgp-afi-aggregate-address.xml.i -->
<leafNode name="as-set">
<properties>
<help>Generate AS-set path information for this aggregate address</help>
@@ -11,4 +11,4 @@
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-allowas-in.xml.i b/interface-definitions/include/bgp/bgp-afi-allowas-in.xml.i
index 77de04ed7..738bf0211 100644
--- a/interface-definitions/include/bgp-afi-allowas-in.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-allowas-in.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-allowas-in.xml.i -->
+<!-- include start from bgp-afi-allowas-in.xml.i -->
<node name="allowas-in">
<properties>
<help>Accept route that contains the local-as in the as-path</help>
@@ -18,4 +18,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-attribute-unchanged.xml.i b/interface-definitions/include/bgp/bgp-afi-attribute-unchanged.xml.i
index fef53dd9d..f407c3f74 100644
--- a/interface-definitions/include/bgp-afi-attribute-unchanged.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-attribute-unchanged.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-attribute-unchanged.xml.i -->
+<!-- include start from bgp-afi-attribute-unchanged.xml.i -->
<node name="attribute-unchanged">
<properties>
<help>BGP attributes are sent unchanged</help>
@@ -24,4 +24,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-capability-orf.xml.i b/interface-definitions/include/bgp/bgp-afi-capability-orf.xml.i
index 9bd265f93..dd5c5f8b2 100644
--- a/interface-definitions/include/bgp-afi-capability-orf.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-capability-orf.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-capability-orf.xml.i -->
+<!-- include start from bgp-afi-capability-orf.xml.i -->
<node name="orf">
<properties>
<help>Advertise ORF capability to this peer</help>
@@ -25,4 +25,4 @@
</node>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-common.xml.i b/interface-definitions/include/bgp/bgp-afi-common.xml.i
index 1a824abfe..7782e7ef2 100644
--- a/interface-definitions/include/bgp-afi-common.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-common.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-common.xml.i -->
+<!-- include start from bgp-afi-common.xml.i -->
<leafNode name="addpath-tx-all">
<properties>
<help>Use addpath to advertise all paths to a neighbor</help>
@@ -11,14 +11,14 @@
<valueless/>
</properties>
</leafNode>
-#include <include/bgp-afi-allowas-in.xml.i>
+#include <include/bgp/bgp-afi-allowas-in.xml.i>
<leafNode name="as-override">
<properties>
<help>AS for routes sent to this peer to be the local AS</help>
<valueless/>
</properties>
</leafNode>
-#include <include/bgp-afi-attribute-unchanged.xml.i>
+#include <include/bgp/bgp-afi-attribute-unchanged.xml.i>
<node name="disable-send-community">
<properties>
<help>Disable sending community attributes to this peer</help>
@@ -43,7 +43,7 @@
<help>Originate default route to this peer</help>
</properties>
<children>
- #include <include/bgp-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
<node name="distribute-list">
@@ -118,21 +118,23 @@
</constraint>
</properties>
</leafNode>
-#include <include/bgp-afi-nexthop-self.xml.i>
+#include <include/bgp/bgp-afi-nexthop-self.xml.i>
<leafNode name="remove-private-as">
<properties>
<help>Remove private AS numbers from AS path in outbound route updates</help>
<valueless/>
</properties>
</leafNode>
-#include <include/bgp-afi-route-map.xml.i>
-#include <include/bgp-afi-route-reflector-client.xml.i>
-#include <include/bgp-afi-route-server-client.xml.i>
-#include <include/bgp-afi-soft-reconfiguration.xml.i>
+#include <include/bgp/bgp-afi-route-map.xml.i>
+#include <include/bgp/bgp-afi-route-reflector-client.xml.i>
+#include <include/bgp/bgp-afi-route-server-client.xml.i>
+#include <include/bgp/bgp-afi-soft-reconfiguration.xml.i>
<leafNode name="unsuppress-map">
<properties>
<help>Route-map to selectively unsuppress suppressed routes</help>
- <valueless/>
+ <completionHelp>
+ <path>policy route-map</path>
+ </completionHelp>
</properties>
</leafNode>
<leafNode name="weight">
@@ -147,4 +149,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-ipv4-prefix-list.xml.i b/interface-definitions/include/bgp/bgp-afi-ipv4-prefix-list.xml.i
index bbbada6bd..133b5da28 100644
--- a/interface-definitions/include/bgp-afi-ipv4-prefix-list.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-ipv4-prefix-list.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-ipv4-prefix-list.xml.i -->
+<!-- include start from bgp-afi-ipv4-prefix-list.xml.i -->
<node name="prefix-list">
<properties>
<help>IPv4-Prefix-list to filter route updates to/from this peer</help>
@@ -22,4 +22,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-ipv6-nexthop-local.xml.i b/interface-definitions/include/bgp/bgp-afi-ipv6-nexthop-local.xml.i
index 4778b392f..c74d81b1f 100644
--- a/interface-definitions/include/bgp-afi-ipv6-nexthop-local.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-ipv6-nexthop-local.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-ipv6-nexthop-local.xml.i -->
+<!-- include start from bgp-afi-ipv6-nexthop-local.xml.i -->
<node name="nexthop-local">
<properties>
<help>Nexthop attributes</help>
@@ -12,4 +12,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-ipv6-prefix-list.xml.i b/interface-definitions/include/bgp/bgp-afi-ipv6-prefix-list.xml.i
index 8ae7837e9..d597b7c99 100644
--- a/interface-definitions/include/bgp-afi-ipv6-prefix-list.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-ipv6-prefix-list.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-ipv6-prefix-list.xml.i -->
+<!-- include start from bgp-afi-ipv6-prefix-list.xml.i -->
<node name="prefix-list">
<properties>
<help>Prefix-list to filter route updates to/from this peer</help>
@@ -22,4 +22,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-afi-l2vpn-common.xml.i b/interface-definitions/include/bgp/bgp-afi-l2vpn-common.xml.i
new file mode 100644
index 000000000..3e7e4ef78
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-afi-l2vpn-common.xml.i
@@ -0,0 +1,27 @@
+<!-- include start from bgp-afi-l2vpn-common.xml.i -->
+<leafNode name="advertise-default-gw">
+ <properties>
+ <help>Advertise All default g/w mac-ip routes in EVPN</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<leafNode name="advertise-svi-ip">
+ <properties>
+ <help>Advertise svi mac-ip routes in EVPN</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<leafNode name="rd">
+ <properties>
+ <help>Route Distinguisher</help>
+ <valueHelp>
+ <format>txt</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>
+#include <include/bgp/bgp-route-target.xml.i>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-afi-maximum-paths.xml.i b/interface-definitions/include/bgp/bgp-afi-maximum-paths.xml.i
new file mode 100644
index 000000000..6b220caa5
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-afi-maximum-paths.xml.i
@@ -0,0 +1,33 @@
+<!-- include start from bgp-afi-maximum-paths.xml.i -->
+<node name="maximum-paths">
+ <properties>
+ <help>Forward packets over multiple paths</help>
+ </properties>
+ <children>
+ <leafNode name="ebgp">
+ <properties>
+ <help>eBGP maximum paths</help>
+ <valueHelp>
+ <format>u32:1-256</format>
+ <description>Number of paths to consider</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-256"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="ibgp">
+ <properties>
+ <help>iBGP maximum paths</help>
+ <valueHelp>
+ <format>u32:1-256</format>
+ <description>Number of paths to consider</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-256"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-nexthop-self.xml.i b/interface-definitions/include/bgp/bgp-afi-nexthop-self.xml.i
index 0bcc4e937..a299f561e 100644
--- a/interface-definitions/include/bgp-afi-nexthop-self.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-nexthop-self.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-nexthop-self.xml.i -->
+<!-- include start from bgp-afi-nexthop-self.xml.i -->
<node name="nexthop-self">
<properties>
<help>Disable the next hop calculation for this peer</help>
@@ -12,4 +12,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-redistribute-metric-route-map.xml.i b/interface-definitions/include/bgp/bgp-afi-redistribute-metric-route-map.xml.i
index e85bf7d11..4382901c8 100644
--- a/interface-definitions/include/bgp-afi-redistribute-metric-route-map.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-redistribute-metric-route-map.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-redistribute-metric-route-map.xml.i -->
+<!-- include start from bgp-afi-redistribute-metric-route-map.xml.i -->
<leafNode name="metric">
<properties>
<help>Metric for redistributed routes</help>
@@ -8,5 +8,5 @@
</valueHelp>
</properties>
</leafNode>
-#include <include/bgp-route-map.xml.i>
-<!-- included end -->
+#include <include/route-map.xml.i>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-route-map.xml.i b/interface-definitions/include/bgp/bgp-afi-route-map.xml.i
index 5549f56ca..7fac98586 100644
--- a/interface-definitions/include/bgp-afi-route-map.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-route-map.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-route-map.xml.i -->
+<!-- include start from bgp-afi-route-map.xml.i -->
<node name="route-map">
<properties>
<help>Route-map to filter route updates to/from this peer</help>
@@ -22,4 +22,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-route-reflector-client.xml.i b/interface-definitions/include/bgp/bgp-afi-route-reflector-client.xml.i
index f6a9caa61..70fee40f0 100644
--- a/interface-definitions/include/bgp-afi-route-reflector-client.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-route-reflector-client.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-afi-route-reflector-client.xml.i -->
+<!-- include start from bgp-afi-route-reflector-client.xml.i -->
<leafNode name="route-reflector-client">
<properties>
<help>Peer is a route reflector client</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-afi-route-server-client.xml.i b/interface-definitions/include/bgp/bgp-afi-route-server-client.xml.i
index 60de553fe..29719c463 100644
--- a/interface-definitions/include/bgp-afi-route-server-client.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-route-server-client.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-afi-route-server-client.xml.i -->
+<!-- include start from bgp-afi-route-server-client.xml.i -->
<leafNode name="route-server-client">
<properties>
<help>Peer is a route server client</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end --> \ No newline at end of file
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/bgp-afi-soft-reconfiguration.xml.i b/interface-definitions/include/bgp/bgp-afi-soft-reconfiguration.xml.i
index 7af11f8f4..c3f050bb8 100644
--- a/interface-definitions/include/bgp-afi-soft-reconfiguration.xml.i
+++ b/interface-definitions/include/bgp/bgp-afi-soft-reconfiguration.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-afi-soft-reconfiguration.xml.i -->
+<!-- include start from bgp-afi-soft-reconfiguration.xml.i -->
<node name="soft-reconfiguration">
<properties>
<help>Soft reconfiguration for peer</help>
@@ -12,4 +12,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-bfd.xml.i b/interface-definitions/include/bgp/bgp-bfd.xml.i
index fe52b12f2..d918fd673 100644
--- a/interface-definitions/include/bgp-bfd.xml.i
+++ b/interface-definitions/include/bgp/bgp-bfd.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-bfd.xml.i -->
+<!-- include start from bgp-bfd.xml.i -->
<node name="bfd">
<properties>
<help>Enable Bidirectional Forwarding Detection (BFD) support</help>
@@ -12,4 +12,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-capability.xml.i b/interface-definitions/include/bgp/bgp-capability.xml.i
index 8de5bd8ab..89ce19ca6 100644
--- a/interface-definitions/include/bgp-capability.xml.i
+++ b/interface-definitions/include/bgp/bgp-capability.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-capability.xml.i -->
+<!-- include start from bgp-capability.xml.i -->
<node name="capability">
<properties>
<help>Advertise capabilities to this peer-group</help>
@@ -18,4 +18,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-common-config.xml.i b/interface-definitions/include/bgp/bgp-common-config.xml.i
new file mode 100644
index 000000000..ae0e8b178
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-common-config.xml.i
@@ -0,0 +1,825 @@
+<!-- include start from bgp/bgp-common-config.xml.i -->
+<node name="address-family">
+ <properties>
+ <help>BGP address-family parameters</help>
+ </properties>
+ <children>
+ <node name="ipv4-unicast">
+ <properties>
+ <help>IPv4 BGP settings</help>
+ </properties>
+ <children>
+ <tagNode name="aggregate-address">
+ <properties>
+ <help>BGP aggregate network</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>BGP aggregate network</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-aggregate-address.xml.i>
+ </children>
+ </tagNode>
+ <tagNode name="network">
+ <properties>
+ <help>BGP network</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>BGP network</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="backdoor">
+ <properties>
+ <help>Network as a backdoor route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ #include <include/route-map.xml.i>
+ </children>
+ </tagNode>
+ #include <include/bgp/bgp-afi-maximum-paths.xml.i>
+ <node name="redistribute">
+ <properties>
+ <help>Redistribute routes from other protocols into BGP</help>
+ </properties>
+ <children>
+ <node name="connected">
+ <properties>
+ <help>Redistribute connected routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="isis">
+ <properties>
+ <help>Redistribute IS-IS routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="kernel">
+ <properties>
+ <help>Redistribute kernel routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="ospf">
+ <properties>
+ <help>Redistribute OSPF routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="rip">
+ <properties>
+ <help>Redistribute RIP routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="static">
+ <properties>
+ <help>Redistribute static routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <leafNode name="table">
+ <properties>
+ <help>Redistribute non-main Kernel Routing Table</help>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="ipv6-unicast">
+ <properties>
+ <help>IPv6 BGP settings</help>
+ </properties>
+ <children>
+ <tagNode name="aggregate-address">
+ <properties>
+ <help>BGP aggregate network</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>Aggregate network</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-aggregate-address.xml.i>
+ </children>
+ </tagNode>
+ <tagNode name="network">
+ <properties>
+ <help>BGP network</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>Aggregate network</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <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/route-map.xml.i>
+ </children>
+ </tagNode>
+ #include <include/bgp/bgp-afi-maximum-paths.xml.i>
+ <node name="redistribute">
+ <properties>
+ <help>Redistribute routes from other protocols into BGP</help>
+ </properties>
+ <children>
+ <node name="connected">
+ <properties>
+ <help>Redistribute connected routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="kernel">
+ <properties>
+ <help>Redistribute kernel routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="ospfv3">
+ <properties>
+ <help>Redistribute OSPFv3 routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="ripng">
+ <properties>
+ <help>Redistribute RIPng routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <node name="static">
+ <properties>
+ <help>Redistribute static routes into BGP</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-redistribute-metric-route-map.xml.i>
+ </children>
+ </node>
+ <leafNode name="table">
+ <properties>
+ <help>Redistribute non-main Kernel Routing Table</help>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="l2vpn-evpn">
+ <properties>
+ <help>L2VPN EVPN BGP settings</help>
+ </properties>
+ <children>
+ <leafNode name="advertise-all-vni">
+ <properties>
+ <help>Advertise All local VNIs</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ #include <include/bgp/bgp-afi-l2vpn-common.xml.i>
+ <leafNode name="advertise-pip">
+ <properties>
+ <help>EVPN system primary IP</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IP address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="rt-auto-derive">
+ <properties>
+ <help>Auto derivation of Route Target (RFC8365)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="flooding">
+ <properties>
+ <help>Specify handling for BUM packets</help>
+ </properties>
+ <children>
+ <leafNode name="disable">
+ <properties>
+ <help>Do not flood any BUM packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="head-end-replication">
+ <properties>
+ <help>Flood BUM packets using head-end replication</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <tagNode name="vni">
+ <properties>
+ <help>VXLAN Network Identifier</help>
+ <valueHelp>
+ <format>u32:1-16777215</format>
+ <description>VNI number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-16777215"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-l2vpn-common.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+</node>
+<node name="listen">
+ <properties>
+ <help>Listen for and accept BGP dynamic neighbors from range</help>
+ </properties>
+ <children>
+ <leafNode name="limit">
+ <properties>
+ <help>Maximum number of dynamic neighbors that can be created</help>
+ <valueHelp>
+ <format>u32:1-5000</format>
+ <description>BGP neighbor limit</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-5000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <tagNode name="range">
+ <properties>
+ <help>BGP dynamic neighbors listen range</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>IPv4 dynamic neighbors listen range</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>IPv6 dynamic neighbors listen range</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-peer-group.xml.i>
+ </children>
+ </tagNode>
+ </children>
+</node>
+<tagNode name="neighbor">
+ <properties>
+ <help>BGP neighbor</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>BGP neighbor IP address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>BGP neighbor IPv6 address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ <validator name="ipv6-address"/>
+ <validator name="interface-name"/>
+ </constraint>
+ </properties>
+ <children>
+ <node name="address-family">
+ <properties>
+ <help>Parameters relating to IPv4 or IPv6 routes</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-neighbor-afi-ipv4-unicast.xml.i>
+ #include <include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i>
+ #include <include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i>
+ </children>
+ </node>
+ <leafNode name="advertisement-interval">
+ <properties>
+ <help>Minimum interval for sending routing updates</help>
+ <valueHelp>
+ <format>u32:0-600</format>
+ <description>Advertisement interval in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-600"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/bgp/bgp-bfd.xml.i>
+ #include <include/bgp/bgp-capability.xml.i>
+ #include <include/bgp/bgp-description.xml.i>
+ #include <include/bgp/bgp-disable-capability-negotiation.xml.i>
+ #include <include/bgp/bgp-disable-connected-check.xml.i>
+ #include <include/bgp/bgp-ebgp-multihop.xml.i>
+ <node name="interface">
+ <properties>
+ <help>Interface parameters</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-peer-group.xml.i>
+ #include <include/bgp/bgp-remote-as.xml.i>
+ <node name="v6only">
+ <properties>
+ <help>Enable BGP with v6 link-local only</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-peer-group.xml.i>
+ #include <include/bgp/bgp-remote-as.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ #include <include/bgp/bgp-local-as.xml.i>
+ #include <include/bgp/bgp-override-capability.xml.i>
+ #include <include/bgp/bgp-passive.xml.i>
+ #include <include/bgp/bgp-password.xml.i>
+ #include <include/bgp/bgp-peer-group.xml.i>
+ <leafNode name="port">
+ <properties>
+ <help>Neighbor BGP port</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Neighbor BGP port number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/bgp/bgp-remote-as.xml.i>
+ #include <include/bgp/bgp-shutdown.xml.i>
+ <leafNode name="strict-capability-match">
+ <properties>
+ <help>Enable strict capability negotiation</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="timers">
+ <properties>
+ <help>Neighbor timers</help>
+ </properties>
+ <children>
+ <leafNode name="connect">
+ <properties>
+ <help>BGP connect timer for this neighbor</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Connect timer in seconds</description>
+ </valueHelp>
+ <valueHelp>
+ <format>0</format>
+ <description>Disable connect timer</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/bgp/bgp-timers-holdtime.xml.i>
+ #include <include/bgp/bgp-timers-keepalive.xml.i>
+ </children>
+ </node>
+ #include <include/bgp/bgp-ttl-security.xml.i>
+ #include <include/bgp/bgp-update-source.xml.i>
+ </children>
+</tagNode>
+<node name="parameters">
+ <properties>
+ <help>BGP parameters</help>
+ </properties>
+ <children>
+ <leafNode name="always-compare-med">
+ <properties>
+ <help>Always compare MEDs from different neighbors</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="bestpath">
+ <properties>
+ <help>Default bestpath selection mechanism</help>
+ </properties>
+ <children>
+ <node name="as-path">
+ <properties>
+ <help>AS-path attribute comparison parameters</help>
+ </properties>
+ <children>
+ <leafNode name="confed">
+ <properties>
+ <help>Compare AS-path lengths including confederation sets and sequences</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="ignore">
+ <properties>
+ <help>Ignore AS-path length in selecting a route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="multipath-relax">
+ <properties>
+ <help>Allow load sharing across routes that have different AS paths (but same length)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="compare-routerid">
+ <properties>
+ <help>Compare the router-id for identical EBGP paths</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="med">
+ <properties>
+ <help>MED attribute comparison parameters</help>
+ </properties>
+ <children>
+ <leafNode name="confed">
+ <properties>
+ <help>Compare MEDs among confederation paths</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="missing-as-worst">
+ <properties>
+ <help>Treat missing route as a MED as the least preferred one</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <leafNode name="cluster-id">
+ <properties>
+ <help>Route-reflector cluster-id</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Route-reflector cluster-id</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <node name="confederation">
+ <properties>
+ <help>AS confederation parameters</help>
+ </properties>
+ <children>
+ <leafNode name="identifier">
+ <properties>
+ <help>Confederation AS identifier [REQUIRED]</help>
+ <valueHelp>
+ <format>u32:1-4294967294</format>
+ <description>Confederation AS id</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="peers">
+ <properties>
+ <help>Peer ASs in the BGP confederation</help>
+ <valueHelp>
+ <format>u32:1-4294967294</format>
+ <description>Peer AS number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <node name="dampening">
+ <properties>
+ <help>Enable route-flap dampening</help>
+ </properties>
+ <children>
+ <leafNode name="half-life">
+ <properties>
+ <help>Half-life time for dampening [REQUIRED]</help>
+ <valueHelp>
+ <format>u32:1-45</format>
+ <description>Half-life penalty in minutes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-45"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="max-suppress-time">
+ <properties>
+ <help>Maximum duration to suppress a stable route [REQUIRED]</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Maximum suppress duration in minutes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="re-use">
+ <properties>
+ <help>Threshold to start reusing a route [REQUIRED]</help>
+ <valueHelp>
+ <format>u32:1-20000</format>
+ <description>Re-use penalty points</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-20000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="start-suppress-time">
+ <properties>
+ <help>When to start suppressing a route [REQUIRED]</help>
+ <valueHelp>
+ <format>u32:1-20000</format>
+ <description>Start-suppress penalty points</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-20000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <node name="default">
+ <properties>
+ <help>BGP defaults</help>
+ </properties>
+ <children>
+ <leafNode name="local-pref">
+ <properties>
+ <help>Default local preference</help>
+ <valueHelp>
+ <format>u32</format>
+ <description>Local preference</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="no-ipv4-unicast">
+ <properties>
+ <help>Deactivate IPv4 unicast for a peer by default</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="deterministic-med">
+ <properties>
+ <help>Compare MEDs between different peers in the same AS</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="distance">
+ <properties>
+ <help>Administratives distances for BGP routes</help>
+ </properties>
+ <children>
+ <node name="global">
+ <properties>
+ <help>Global administratives distances for BGP routes</help>
+ </properties>
+ <children>
+ <leafNode name="external">
+ <properties>
+ <help>Administrative distance for external BGP routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Administrative distance for external BGP routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="internal">
+ <properties>
+ <help>Administrative distance for internal BGP routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Administrative distance for internal BGP routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="local">
+ <properties>
+ <help>Administrative distance for local BGP routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Administrative distance for internal BGP routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <tagNode name="prefix">
+ <properties>
+ <help>Administrative distance for a specific BGP prefix</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>Administrative distance for a specific BGP prefix</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="distance">
+ <properties>
+ <help>Administrative distance for prefix</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Administrative distance for external BGP routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <leafNode name="ebgp-requires-policy">
+ <properties>
+ <help>Require in and out policy for eBGP peers (RFC8212)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="graceful-restart">
+ <properties>
+ <help>Graceful restart capability parameters</help>
+ </properties>
+ <children>
+ <leafNode name="stalepath-time">
+ <properties>
+ <help>Maximum time to hold onto restarting neighbors stale paths</help>
+ <valueHelp>
+ <format>u32:1-3600</format>
+ <description>Hold time in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-3600"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="graceful-shutdown">
+ <properties>
+ <help>Graceful shutdown</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="log-neighbor-changes">
+ <properties>
+ <help>Log neighbor up/down changes and reset reason</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="network-import-check">
+ <properties>
+ <help>Enable IGP route check for network statements</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="no-client-to-client-reflection">
+ <properties>
+ <help>Disable client to client route reflection</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="no-fast-external-failover">
+ <properties>
+ <help>Disable immediate session reset on peer link down event</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="router-id">
+ <properties>
+ <help>BGP router id</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>BGP router id</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<tagNode name="peer-group">
+ <properties>
+ <help>BGP peer-group</help>
+ </properties>
+ <children>
+ <node name="address-family">
+ <properties>
+ <help>BGP peer-group address-family parameters</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-neighbor-afi-ipv4-unicast.xml.i>
+ #include <include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i>
+ #include <include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i>
+ </children>
+ </node>
+ #include <include/bgp/bgp-bfd.xml.i>
+ #include <include/bgp/bgp-capability.xml.i>
+ #include <include/bgp/bgp-description.xml.i>
+ #include <include/bgp/bgp-disable-capability-negotiation.xml.i>
+ #include <include/bgp/bgp-disable-connected-check.xml.i>
+ #include <include/bgp/bgp-ebgp-multihop.xml.i>
+ #include <include/bgp/bgp-local-as.xml.i>
+ #include <include/bgp/bgp-override-capability.xml.i>
+ #include <include/bgp/bgp-passive.xml.i>
+ #include <include/bgp/bgp-password.xml.i>
+ #include <include/bgp/bgp-remote-as.xml.i>
+ #include <include/bgp/bgp-shutdown.xml.i>
+ #include <include/bgp/bgp-ttl-security.xml.i>
+ #include <include/bgp/bgp-update-source.xml.i>
+ </children>
+</tagNode>
+#include <include/route-map.xml.i>
+<node name="timers">
+ <properties>
+ <help>BGP protocol timers</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-timers-holdtime.xml.i>
+ #include <include/bgp/bgp-timers-keepalive.xml.i>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-description.xml.i b/interface-definitions/include/bgp/bgp-description.xml.i
index e1766cb9f..308bbec12 100644
--- a/interface-definitions/include/bgp-description.xml.i
+++ b/interface-definitions/include/bgp/bgp-description.xml.i
@@ -1,7 +1,7 @@
-<!-- included start from bgp-description.xml.i -->
+<!-- include start from bgp-description.xml.i -->
<leafNode name="description">
<properties>
<help>Neighbor specific description</help>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-disable-capability-negotiation.xml.i b/interface-definitions/include/bgp/bgp-disable-capability-negotiation.xml.i
index a43c6e8b9..74c3321d9 100644
--- a/interface-definitions/include/bgp-disable-capability-negotiation.xml.i
+++ b/interface-definitions/include/bgp/bgp-disable-capability-negotiation.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-disable-capability-negotiation.xml.i -->
+<!-- include start from bgp-disable-capability-negotiation.xml.i -->
<leafNode name="disable-capability-negotiation">
<properties>
<help>Disable capability negotiation with this neighbor</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-disable-connected-check.xml.i b/interface-definitions/include/bgp/bgp-disable-connected-check.xml.i
index bb9098bf6..15142b0ac 100644
--- a/interface-definitions/include/bgp-disable-connected-check.xml.i
+++ b/interface-definitions/include/bgp/bgp-disable-connected-check.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-disable-connected-check.xml.i -->
+<!-- include start from bgp-disable-connected-check.xml.i -->
<leafNode name="disable-connected-check">
<properties>
<help>Disable check to see if eBGP peer address is a connected route</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-ebgp-multihop.xml.i b/interface-definitions/include/bgp/bgp-ebgp-multihop.xml.i
index 6459fcf47..48580af3c 100644
--- a/interface-definitions/include/bgp-ebgp-multihop.xml.i
+++ b/interface-definitions/include/bgp/bgp-ebgp-multihop.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-ebgp-multihop.xml.i -->
+<!-- include start from bgp-ebgp-multihop.xml.i -->
<leafNode name="ebgp-multihop">
<properties>
<help>Allow this EBGP neighbor to not be on a directly connected network</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-local-as.xml.i b/interface-definitions/include/bgp/bgp-local-as.xml.i
index cf55ce476..7fc896a31 100644
--- a/interface-definitions/include/bgp-local-as.xml.i
+++ b/interface-definitions/include/bgp/bgp-local-as.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-local-as.xml.i -->
+<!-- include start from bgp-local-as.xml.i -->
<tagNode name="local-as">
<properties>
<help>Local AS number [REQUIRED]</help>
@@ -19,4 +19,4 @@
</leafNode>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i b/interface-definitions/include/bgp/bgp-neighbor-afi-ipv4-unicast.xml.i
index 8f6cf06b1..945483276 100644
--- a/interface-definitions/include/bgp-neighbor-afi-ipv4-unicast.xml.i
+++ b/interface-definitions/include/bgp/bgp-neighbor-afi-ipv4-unicast.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-neighbor-afi-ipv4-unicast.xml.i -->
+<!-- include start from bgp-neighbor-afi-ipv4-unicast.xml.i -->
<node name="ipv4-unicast">
<properties>
<help>IPv4 BGP neighbor parameters</help>
@@ -9,12 +9,11 @@
<help>Advertise capabilities to this neighbor (IPv4)</help>
</properties>
<children>
- #include <include/bgp-afi-capability-orf.xml.i>
+ #include <include/bgp/bgp-afi-capability-orf.xml.i>
</children>
</node>
- #include <include/bgp-afi-peer-group.xml.i>
- #include <include/bgp-afi-ipv4-prefix-list.xml.i>
- #include <include/bgp-afi-common.xml.i>
+ #include <include/bgp/bgp-afi-ipv4-prefix-list.xml.i>
+ #include <include/bgp/bgp-afi-common.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i b/interface-definitions/include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i
new file mode 100644
index 000000000..4cd676cb4
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-neighbor-afi-ipv6-unicast.xml.i
@@ -0,0 +1,20 @@
+<!-- include start from bgp-neighbor-afi-ipv6-unicast.xml.i -->
+<node name="ipv6-unicast">
+ <properties>
+ <help>IPv6 BGP neighbor parameters</help>
+ </properties>
+ <children>
+ <node name="capability">
+ <properties>
+ <help>Advertise capabilities to this neighbor (IPv6)</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-capability-orf.xml.i>
+ </children>
+ </node>
+ #include <include/bgp/bgp-afi-ipv6-nexthop-local.xml.i>
+ #include <include/bgp/bgp-afi-ipv6-prefix-list.xml.i>
+ #include <include/bgp/bgp-afi-common.xml.i>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i b/interface-definitions/include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i
new file mode 100644
index 000000000..0a9c599fa
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-neighbor-afi-l2vpn-evpn.xml.i
@@ -0,0 +1,16 @@
+<!-- include start from bgp-neighbor-afi-l2vpn-evpn.xml.i -->
+<node name="l2vpn-evpn">
+ <properties>
+ <help>L2VPN EVPN BGP settings</help>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-afi-allowas-in.xml.i>
+ #include <include/bgp/bgp-afi-attribute-unchanged.xml.i>
+ #include <include/bgp/bgp-afi-nexthop-self.xml.i>
+ #include <include/bgp/bgp-afi-route-map.xml.i>
+ #include <include/bgp/bgp-afi-route-reflector-client.xml.i>
+ #include <include/bgp/bgp-afi-route-server-client.xml.i>
+ #include <include/bgp/bgp-afi-soft-reconfiguration.xml.i>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-override-capability.xml.i b/interface-definitions/include/bgp/bgp-override-capability.xml.i
index 88c277c8b..1e51a49d5 100644
--- a/interface-definitions/include/bgp-override-capability.xml.i
+++ b/interface-definitions/include/bgp/bgp-override-capability.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-override-capability.xml.i -->
+<!-- include start from bgp-override-capability.xml.i -->
<leafNode name="override-capability">
<properties>
<help>Ignore capability negotiation with specified neighbor</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-passive.xml.i b/interface-definitions/include/bgp/bgp-passive.xml.i
index ada961866..033cf8231 100644
--- a/interface-definitions/include/bgp-passive.xml.i
+++ b/interface-definitions/include/bgp/bgp-passive.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from bgp-passive.xml.i -->
+<!-- include start from bgp-passive.xml.i -->
<leafNode name="passive">
<properties>
<help>Do not initiate a session with this neighbor</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-password.xml.i b/interface-definitions/include/bgp/bgp-password.xml.i
index 5b68a2d71..f5878cce9 100644
--- a/interface-definitions/include/bgp-password.xml.i
+++ b/interface-definitions/include/bgp/bgp-password.xml.i
@@ -1,7 +1,7 @@
-<!-- included start from bgp-password.xml.i -->
+<!-- include start from bgp-password.xml.i -->
<leafNode name="password">
<properties>
<help>BGP MD5 password</help>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-peer-group.xml.i b/interface-definitions/include/bgp/bgp-peer-group.xml.i
index 73c80e0e4..8fc50794d 100644
--- a/interface-definitions/include/bgp-peer-group.xml.i
+++ b/interface-definitions/include/bgp/bgp-peer-group.xml.i
@@ -1,11 +1,14 @@
-<!-- included start from bgp-peer-group.xml.i -->
+<!-- include start from bgp-peer-group.xml.i -->
<leafNode name="peer-group">
<properties>
<help>Peer group for this peer</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_bgp_peer_groups.sh</script>
+ </completionHelp>
<valueHelp>
<format>txt</format>
<description>Peer-group name</description>
</valueHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-remote-as.xml.i b/interface-definitions/include/bgp/bgp-remote-as.xml.i
index de3f4d2ad..f036fe13d 100644
--- a/interface-definitions/include/bgp-remote-as.xml.i
+++ b/interface-definitions/include/bgp/bgp-remote-as.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-remote-as.xml.i -->
+<!-- include start from bgp-remote-as.xml.i -->
<leafNode name="remote-as">
<properties>
<help>Neighbor BGP AS number [REQUIRED]</help>
@@ -24,4 +24,4 @@
<constraintErrorMessage>Invalid AS number</constraintErrorMessage>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/bgp-route-target.xml.i b/interface-definitions/include/bgp/bgp-route-target.xml.i
new file mode 100644
index 000000000..c05ac5dc2
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-route-target.xml.i
@@ -0,0 +1,45 @@
+<!-- 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/bgp/bgp-shutdown.xml.i b/interface-definitions/include/bgp/bgp-shutdown.xml.i
new file mode 100644
index 000000000..f920e9579
--- /dev/null
+++ b/interface-definitions/include/bgp/bgp-shutdown.xml.i
@@ -0,0 +1,8 @@
+<!-- include start from bgp-shutdown.xml.i -->
+<leafNode name="shutdown">
+ <properties>
+ <help>Administratively shut down this neighbor</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-timers-holdtime.xml.i b/interface-definitions/include/bgp/bgp-timers-holdtime.xml.i
index 09924574b..9c16127b5 100644
--- a/interface-definitions/include/bgp-timers-holdtime.xml.i
+++ b/interface-definitions/include/bgp/bgp-timers-holdtime.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-timers-holdtime.xml.i -->
+<!-- include start from bgp-timers-holdtime.xml.i -->
<leafNode name="holdtime">
<properties>
<help>BGP hold timer for this neighbor</help>
@@ -15,4 +15,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-timers-keepalive.xml.i b/interface-definitions/include/bgp/bgp-timers-keepalive.xml.i
index 7d294c9d6..8c3e66c6a 100644
--- a/interface-definitions/include/bgp-timers-keepalive.xml.i
+++ b/interface-definitions/include/bgp/bgp-timers-keepalive.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-timers-keepalive.xml.i -->
+<!-- include start from bgp-timers-keepalive.xml.i -->
<leafNode name="keepalive">
<properties>
<help>BGP keepalive interval for this neighbor</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-ttl-security.xml.i b/interface-definitions/include/bgp/bgp-ttl-security.xml.i
index 3f4d1786d..1fb1c2c55 100644
--- a/interface-definitions/include/bgp-ttl-security.xml.i
+++ b/interface-definitions/include/bgp/bgp-ttl-security.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from bgp-ttl-security.xml.i -->
+<!-- include start from bgp-ttl-security.xml.i -->
<node name="ttl-security">
<properties>
<help>Ttl security mechanism</help>
@@ -18,4 +18,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/bgp-update-source.xml.i b/interface-definitions/include/bgp/bgp-update-source.xml.i
index a8b212720..f4ccc3553 100644
--- a/interface-definitions/include/bgp-update-source.xml.i
+++ b/interface-definitions/include/bgp/bgp-update-source.xml.i
@@ -1,10 +1,11 @@
-<!-- included start from bgp-update-source.xml.i -->
+<!-- include start from bgp-update-source.xml.i -->
<leafNode name="update-source">
<!-- Need to check format interfaces -->
<properties>
<help>Source IP of routing updates</help>
<completionHelp>
<script>${vyos_completion_dir}/list_local_ips.sh --both</script>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
</completionHelp>
<valueHelp>
<format>ipv4</format>
@@ -25,4 +26,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/certificate-ca.xml.i b/interface-definitions/include/certificate-ca.xml.i
index df12746aa..b97378658 100644
--- a/interface-definitions/include/certificate-ca.xml.i
+++ b/interface-definitions/include/certificate-ca.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from certificate-ca.xml.i -->
+<!-- include start from certificate-ca.xml.i -->
<leafNode name="ca-cert-file">
<properties>
<help>Certificate Authority in x509 PEM format</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/certificate-key.xml.i b/interface-definitions/include/certificate-key.xml.i
index 924823c76..1db9dd069 100644
--- a/interface-definitions/include/certificate-key.xml.i
+++ b/interface-definitions/include/certificate-key.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from certificate-key.xml.i -->
+<!-- include start from certificate-key.xml.i -->
<leafNode name="key-file">
<properties>
<help>Certificate private key in x509 PEM format</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/certificate.xml.i b/interface-definitions/include/certificate.xml.i
index 724a8a27f..fb5be45cc 100644
--- a/interface-definitions/include/certificate.xml.i
+++ b/interface-definitions/include/certificate.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from certificate.xml.i -->
+<!-- include start from certificate.xml.i -->
<leafNode name="cert-file">
<properties>
<help>Certificate public key in x509 PEM format</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/dhcp-options.xml.i b/interface-definitions/include/dhcp-options.xml.i
index df9c7a97a..8972b53e9 100644
--- a/interface-definitions/include/dhcp-options.xml.i
+++ b/interface-definitions/include/dhcp-options.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from dhcp-options.xml.i -->
+<!-- include start from dhcp-options.xml.i -->
<node name="dhcp-options">
<properties>
<help>DHCP client settings/options</help>
@@ -25,6 +25,18 @@
<valueless/>
</properties>
</leafNode>
+ <leafNode name="default-route-distance">
+ <properties>
+ <help>Distance for the default route from DHCP server</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for the default route from DHCP server (default 210)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/dhcp-server-domain-search.xml.i b/interface-definitions/include/dhcp-server-domain-search.xml.i
index 9b3568b72..4fc55097b 100644
--- a/interface-definitions/include/dhcp-server-domain-search.xml.i
+++ b/interface-definitions/include/dhcp-server-domain-search.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from dhcp-server-domain-search.xml.i -->
+<!-- include start from dhcp-server-domain-search.xml.i -->
<leafNode name="domain-search">
<properties>
<help>Client Domain Name search list</help>
@@ -9,4 +9,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/dhcpv6-options.xml.i b/interface-definitions/include/dhcpv6-options.xml.i
index 33ba39592..a569659a4 100644
--- a/interface-definitions/include/dhcpv6-options.xml.i
+++ b/interface-definitions/include/dhcpv6-options.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from dhcpv6-options.xml.i -->
+<!-- include start from dhcpv6-options.xml.i -->
<node name="dhcpv6-options">
<properties>
<help>DHCPv6 client settings/options</help>
@@ -97,4 +97,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/generic-disable-node.xml.i b/interface-definitions/include/generic-disable-node.xml.i
index 520383afb..bb4fa5c4b 100644
--- a/interface-definitions/include/generic-disable-node.xml.i
+++ b/interface-definitions/include/generic-disable-node.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from generic-disable-node.xml.i -->
+<!-- include start from generic-disable-node.xml.i -->
<leafNode name="disable">
<properties>
<help>Temporary disable</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-arp-cache-timeout.xml.i b/interface-definitions/include/interface-arp-cache-timeout.xml.i
index 6dfebfee4..09fd70afc 100644
--- a/interface-definitions/include/interface-arp-cache-timeout.xml.i
+++ b/interface-definitions/include/interface-arp-cache-timeout.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>30</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-description.xml.i b/interface-definitions/include/interface-description.xml.i
index daf09d8bc..b16c562bb 100644
--- a/interface-definitions/include/interface-description.xml.i
+++ b/interface-definitions/include/interface-description.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-description.xml.i -->
+<!-- include start from interface-description.xml.i -->
<leafNode name="description">
<properties>
<help>Interface specific description</help>
@@ -8,4 +8,4 @@
<constraintErrorMessage>Description too long (limit 256 characters)</constraintErrorMessage>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-dial-on-demand.xml.i b/interface-definitions/include/interface-dial-on-demand.xml.i
index 8fba8099d..5067e45df 100644
--- a/interface-definitions/include/interface-dial-on-demand.xml.i
+++ b/interface-definitions/include/interface-dial-on-demand.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-disable-arp-filter.xml.i b/interface-definitions/include/interface-disable-arp-filter.xml.i
index 4de3ca893..5f118d49c 100644
--- a/interface-definitions/include/interface-disable-arp-filter.xml.i
+++ b/interface-definitions/include/interface-disable-arp-filter.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-disable-forwarding.xml.i b/interface-definitions/include/interface-disable-forwarding.xml.i
index 7cbb726ec..fdce8f846 100644
--- a/interface-definitions/include/interface-disable-forwarding.xml.i
+++ b/interface-definitions/include/interface-disable-forwarding.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from interface-disable-forwarding.xml.i -->
+<!-- include start from interface-disable-forwarding.xml.i -->
<leafNode name="disable-forwarding">
<properties>
<help>Disable IPv4 forwarding on this interface</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-disable-link-detect.xml.i b/interface-definitions/include/interface-disable-link-detect.xml.i
index 4298b4b5d..60c5f635b 100644
--- a/interface-definitions/include/interface-disable-link-detect.xml.i
+++ b/interface-definitions/include/interface-disable-link-detect.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-disable.xml.i b/interface-definitions/include/interface-disable.xml.i
index 5d73d54ba..5a058df01 100644
--- a/interface-definitions/include/interface-disable.xml.i
+++ b/interface-definitions/include/interface-disable.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from interface-disable.xml.i -->
+<!-- include start from interface-disable.xml.i -->
<leafNode name="disable">
<properties>
<help>Administratively disable interface</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-eapol.xml.i b/interface-definitions/include/interface-eapol.xml.i
index 8b33b4acf..fafa75f1a 100644
--- a/interface-definitions/include/interface-eapol.xml.i
+++ b/interface-definitions/include/interface-eapol.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-eapol.xml.i -->
+<!-- include start from interface-eapol.xml.i -->
<node name="eapol">
<properties>
<help>Extensible Authentication Protocol over Local Area Network</help>
@@ -9,4 +9,4 @@
#include <include/certificate-key.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-enable-arp-accept.xml.i b/interface-definitions/include/interface-enable-arp-accept.xml.i
index 688b3572e..bec08a708 100644
--- a/interface-definitions/include/interface-enable-arp-accept.xml.i
+++ b/interface-definitions/include/interface-enable-arp-accept.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-enable-arp-announce.xml.i b/interface-definitions/include/interface-enable-arp-announce.xml.i
index c84bb7ea9..ef9e5db1e 100644
--- a/interface-definitions/include/interface-enable-arp-announce.xml.i
+++ b/interface-definitions/include/interface-enable-arp-announce.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-enable-arp-ignore.xml.i b/interface-definitions/include/interface-enable-arp-ignore.xml.i
index 741771a89..0a33a2c9a 100644
--- a/interface-definitions/include/interface-enable-arp-ignore.xml.i
+++ b/interface-definitions/include/interface-enable-arp-ignore.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-enable-proxy-arp.xml.i b/interface-definitions/include/interface-enable-proxy-arp.xml.i
index 08351e673..a0993539f 100644
--- a/interface-definitions/include/interface-enable-proxy-arp.xml.i
+++ b/interface-definitions/include/interface-enable-proxy-arp.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-hw-id.xml.i b/interface-definitions/include/interface-hw-id.xml.i
index 55ef55add..78e8613d8 100644
--- a/interface-definitions/include/interface-hw-id.xml.i
+++ b/interface-definitions/include/interface-hw-id.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-ipv4-options.xml.i b/interface-definitions/include/interface-ipv4-options.xml.i
index c63f89890..64672f164 100644
--- a/interface-definitions/include/interface-ipv4-options.xml.i
+++ b/interface-definitions/include/interface-ipv4-options.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-ipv4-options.xml.i -->
+<!-- include start from interface-ipv4-options.xml.i -->
<node name="ip">
<properties>
<help>IPv4 routing parameters</help>
@@ -15,4 +15,4 @@
#include <include/interface-source-validation.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-ipv6-options.xml.i b/interface-definitions/include/interface-ipv6-options.xml.i
index a94c6572b..a15aea9c1 100644
--- a/interface-definitions/include/interface-ipv6-options.xml.i
+++ b/interface-definitions/include/interface-ipv6-options.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-ipv6-options.xml.i -->
+<!-- include start from interface-ipv6-options.xml.i -->
<node name="ipv6">
<properties>
<help>IPv6 routing parameters</help>
@@ -9,4 +9,4 @@
#include <include/ipv6-dup-addr-detect-transmits.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mac.xml.i b/interface-definitions/include/interface-mac.xml.i
index 87dc5fb60..160b42b2e 100644
--- a/interface-definitions/include/interface-mac.xml.i
+++ b/interface-definitions/include/interface-mac.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from mac.xml.i -->
+<!-- include start from mac.xml.i -->
<leafNode name="mac">
<properties>
<help>Media Access Control (MAC) address</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mirror.xml.i b/interface-definitions/include/interface-mirror.xml.i
index d34132a9c..445e214fe 100644
--- a/interface-definitions/include/interface-mirror.xml.i
+++ b/interface-definitions/include/interface-mirror.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-mirror.xml.i -->
+<!-- include start from interface-mirror.xml.i -->
<node name="mirror">
<properties>
<help>Incoming/outgoing packet mirroring destination</help>
@@ -22,4 +22,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mtu-1200-16000.xml.i b/interface-definitions/include/interface-mtu-1200-16000.xml.i
index 04b5ec8ac..0187c5991 100644
--- a/interface-definitions/include/interface-mtu-1200-16000.xml.i
+++ b/interface-definitions/include/interface-mtu-1200-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>1500</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mtu-1450-16000.xml.i b/interface-definitions/include/interface-mtu-1450-16000.xml.i
index 41dd5fb00..84268586e 100644
--- a/interface-definitions/include/interface-mtu-1450-16000.xml.i
+++ b/interface-definitions/include/interface-mtu-1450-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>1500</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mtu-64-8024.xml.i b/interface-definitions/include/interface-mtu-64-8024.xml.i
index 0a455bc64..6a7ab8a80 100644
--- a/interface-definitions/include/interface-mtu-64-8024.xml.i
+++ b/interface-definitions/include/interface-mtu-64-8024.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>1500</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mtu-68-1500.xml.i b/interface-definitions/include/interface-mtu-68-1500.xml.i
index 78c2c6920..ea333edcc 100644
--- a/interface-definitions/include/interface-mtu-68-1500.xml.i
+++ b/interface-definitions/include/interface-mtu-68-1500.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>1500</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-mtu-68-16000.xml.i b/interface-definitions/include/interface-mtu-68-16000.xml.i
index 9f18464bf..a9107c027 100644
--- a/interface-definitions/include/interface-mtu-68-16000.xml.i
+++ b/interface-definitions/include/interface-mtu-68-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -13,4 +13,4 @@
</properties>
<defaultValue>1500</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-parameters-dont-fragment.xml.i b/interface-definitions/include/interface-parameters-dont-fragment.xml.i
new file mode 100644
index 000000000..d6c276d67
--- /dev/null
+++ b/interface-definitions/include/interface-parameters-dont-fragment.xml.i
@@ -0,0 +1,8 @@
+<!-- include start from interface-parameters-df.xml.i -->
+<leafNode name="dont-fragment">
+ <properties>
+ <help>Specifies the usage of the dont fragment (DF) bit</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface-parameters-flowlabel.xml.i b/interface-definitions/include/interface-parameters-flowlabel.xml.i
new file mode 100644
index 000000000..dc651bc9c
--- /dev/null
+++ b/interface-definitions/include/interface-parameters-flowlabel.xml.i
@@ -0,0 +1,15 @@
+<!-- include start from interface-parameters-flowlabel.xml.i -->
+<leafNode name="flowlabel">
+ <properties>
+ <help>Specifies the flow label to use in outgoing packets</help>
+ <valueHelp>
+ <format>0x0-0x0FFFFF</format>
+ <description>Tunnel key, 'inherit' or hex value</description>
+ </valueHelp>
+ <constraint>
+ <regex>^((0x){0,1}(0?[0-9A-Fa-f]{1,5})|inherit)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be 'inherit' or a number</constraintErrorMessage>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface-parameters-key.xml.i b/interface-definitions/include/interface-parameters-key.xml.i
new file mode 100644
index 000000000..1891b44b0
--- /dev/null
+++ b/interface-definitions/include/interface-parameters-key.xml.i
@@ -0,0 +1,15 @@
+<!-- include start from interface-parameters-key.xml.i -->
+<leafNode name="key">
+ <properties>
+ <help>Tunnel key</help>
+ <valueHelp>
+ <format>u32</format>
+ <description>Tunnel key</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ <constraintErrorMessage>key must be between 0-4294967295</constraintErrorMessage>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface-parameters-tos.xml.i b/interface-definitions/include/interface-parameters-tos.xml.i
new file mode 100644
index 000000000..06ec2febb
--- /dev/null
+++ b/interface-definitions/include/interface-parameters-tos.xml.i
@@ -0,0 +1,16 @@
+<!-- include start from tunnel-parameters-tos.xml.i -->
+<leafNode name="tos">
+ <properties>
+ <help>Specifies TOS value to use in outgoing packets</help>
+ <valueHelp>
+ <format>0-99</format>
+ <description>Type of Service (TOS)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-99"/>
+ </constraint>
+ <constraintErrorMessage>TOS must be between 0 and 99</constraintErrorMessage>
+ </properties>
+ <defaultValue>inherit</defaultValue>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface-parameters-ttl.xml.i b/interface-definitions/include/interface-parameters-ttl.xml.i
new file mode 100644
index 000000000..a2e13d8d1
--- /dev/null
+++ b/interface-definitions/include/interface-parameters-ttl.xml.i
@@ -0,0 +1,20 @@
+<!-- include start from interface-parameters-ttl.xml.i -->
+<leafNode name="ttl">
+ <properties>
+ <help>Specifies TTL value to use in outgoing packets</help>
+ <valueHelp>
+ <format>0</format>
+ <description>Inherit - copy value from original IP header</description>
+ </valueHelp>
+ <valueHelp>
+ <format>1-255</format>
+ <description>Time to Live</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ <constraintErrorMessage>TTL must be between 0 and 255</constraintErrorMessage>
+ </properties>
+ <defaultValue>0</defaultValue>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface-proxy-arp-pvlan.xml.i b/interface-definitions/include/interface-proxy-arp-pvlan.xml.i
index 02b96e353..484f8fd69 100644
--- a/interface-definitions/include/interface-proxy-arp-pvlan.xml.i
+++ b/interface-definitions/include/interface-proxy-arp-pvlan.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from 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>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-source-validation.xml.i b/interface-definitions/include/interface-source-validation.xml.i
index 32cec464e..be58bce87 100644
--- a/interface-definitions/include/interface-source-validation.xml.i
+++ b/interface-definitions/include/interface-source-validation.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from 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>
@@ -22,4 +22,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-vrf.xml.i b/interface-definitions/include/interface-vrf.xml.i
index e3d6b53e0..81ca0972b 100644
--- a/interface-definitions/include/interface-vrf.xml.i
+++ b/interface-definitions/include/interface-vrf.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from interface-vrf.xml.i -->
+<!-- include start from interface-vrf.xml.i -->
<leafNode name="vrf">
<properties>
<help>VRF instance name</help>
@@ -11,4 +11,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/interface-xdp.xml.i b/interface-definitions/include/interface-xdp.xml.i
index d224c177f..21fcf131d 100644
--- a/interface-definitions/include/interface-xdp.xml.i
+++ b/interface-definitions/include/interface-xdp.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from interface-vrf.xml.i -->
+<!-- include start from interface-vrf.xml.i -->
<leafNode name="xdp">
<properties>
<help>Enable eXpress Data Path</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-address-autoconf.xml.i b/interface-definitions/include/ipv6-address-autoconf.xml.i
index 580f060d7..a84293067 100644
--- a/interface-definitions/include/ipv6-address-autoconf.xml.i
+++ b/interface-definitions/include/ipv6-address-autoconf.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from ipv6-address-autoconf.xml.i -->
+<!-- include start from ipv6-address-autoconf.xml.i -->
<leafNode name="autoconf">
<properties>
<help>Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-address-eui64.xml.i b/interface-definitions/include/ipv6-address-eui64.xml.i
index 093a1dc79..e06e88d52 100644
--- a/interface-definitions/include/ipv6-address-eui64.xml.i
+++ b/interface-definitions/include/ipv6-address-eui64.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ipv6-address-eui64.xml.i -->
+<!-- include start from ipv6-address-eui64.xml.i -->
<leafNode name="eui64">
<properties>
<help>Prefix for IPv6 address with MAC-based EUI-64</help>
@@ -12,4 +12,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-address-no-default-link-local.xml.i b/interface-definitions/include/ipv6-address-no-default-link-local.xml.i
index 1c9e832dc..e803a4d60 100644
--- a/interface-definitions/include/ipv6-address-no-default-link-local.xml.i
+++ b/interface-definitions/include/ipv6-address-no-default-link-local.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from ipv6-address-no-default-link-local.xml.i -->
+<!-- include start from ipv6-address-no-default-link-local.xml.i -->
<leafNode name="no-default-link-local">
<properties>
<help>Remove the default link-local address from the interface</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-address.xml.i b/interface-definitions/include/ipv6-address.xml.i
index 276456248..d934f9021 100644
--- a/interface-definitions/include/ipv6-address.xml.i
+++ b/interface-definitions/include/ipv6-address.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ipv6-address.xml.i -->
+<!-- include start from ipv6-address.xml.i -->
<node name="address">
<properties>
<help>IPv6 address configuration modes</help>
@@ -9,4 +9,4 @@
#include <include/ipv6-address-no-default-link-local.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-disable-forwarding.xml.i b/interface-definitions/include/ipv6-disable-forwarding.xml.i
index 14d9eada9..5f368256b 100644
--- a/interface-definitions/include/ipv6-disable-forwarding.xml.i
+++ b/interface-definitions/include/ipv6-disable-forwarding.xml.i
@@ -1,8 +1,8 @@
-<!-- included start from ipv6-disable-forwarding.xml.i -->
+<!-- include start from ipv6-disable-forwarding.xml.i -->
<leafNode name="disable-forwarding">
<properties>
<help>Disable IPv6 forwarding on this interface</help>
<valueless/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i b/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i
index 61e6669c4..c6265d71a 100644
--- a/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i
+++ b/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ipv6-dup-addr-detect-transmits.xml.i -->
+<!-- include start from ipv6-dup-addr-detect-transmits.xml.i -->
<leafNode name="dup-addr-detect-transmits">
<properties>
<help>Number of NS messages to send while performing DAD (default: 1)</help>
@@ -15,4 +15,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/isis-redistribute-ipv4.xml.i b/interface-definitions/include/isis-redistribute-ipv4.xml.i
index 97ab64250..774086a81 100644
--- a/interface-definitions/include/isis-redistribute-ipv4.xml.i
+++ b/interface-definitions/include/isis-redistribute-ipv4.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from isis-redistribute-ipv4.xml.i -->
+<!-- include start from isis-redistribute-ipv4.xml.i -->
<node name="level-1">
<properties>
<help>Redistribute into level-1</help>
@@ -53,4 +53,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/listen-address-ipv4.xml.i b/interface-definitions/include/listen-address-ipv4.xml.i
index 530dbf619..ee52cebe8 100644
--- a/interface-definitions/include/listen-address-ipv4.xml.i
+++ b/interface-definitions/include/listen-address-ipv4.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from listen-address-ipv4.xml.i -->
+<!-- include start from listen-address-ipv4.xml.i -->
<leafNode name="listen-address">
<properties>
<help>Local IPv4 addresses for service to listen on</help>
@@ -15,4 +15,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/listen-address.xml.i b/interface-definitions/include/listen-address.xml.i
index 5bfb7eb38..9b86851c7 100644
--- a/interface-definitions/include/listen-address.xml.i
+++ b/interface-definitions/include/listen-address.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from listen-address.xml.i -->
+<!-- include start from listen-address.xml.i -->
<leafNode name="listen-address">
<properties>
<help>Local IP addresses for service to listen on</help>
@@ -20,4 +20,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/nat-address.xml.i b/interface-definitions/include/nat-address.xml.i
index 846ef3dec..a6460ac0f 100644
--- a/interface-definitions/include/nat-address.xml.i
+++ b/interface-definitions/include/nat-address.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from nat-address.xml.i -->
+<!-- include start from nat-address.xml.i -->
<leafNode name="address">
<properties>
<help>IP address, subnet, or range</help>
@@ -36,4 +36,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/nat-interface.xml.i b/interface-definitions/include/nat-interface.xml.i
index e42003530..68969472f 100644
--- a/interface-definitions/include/nat-interface.xml.i
+++ b/interface-definitions/include/nat-interface.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from nat-interface.xml.i -->
+<!-- include start from nat-interface.xml.i -->
<leafNode name="outbound-interface">
<properties>
<help>Outbound interface of NAT traffic</help>
@@ -8,4 +8,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/nat-port.xml.i b/interface-definitions/include/nat-port.xml.i
index 6465c00e9..ebba43712 100644
--- a/interface-definitions/include/nat-port.xml.i
+++ b/interface-definitions/include/nat-port.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from nat-port.xml.i -->
+<!-- include start from nat-port.xml.i -->
<leafNode name="port">
<properties>
<help>Port number</help>
@@ -16,4 +16,4 @@
</valueHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/nat-rule.xml.i b/interface-definitions/include/nat-rule.xml.i
index 7ef90f07e..579d19bdd 100644
--- a/interface-definitions/include/nat-rule.xml.i
+++ b/interface-definitions/include/nat-rule.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from nat-rule.xml.i -->
+<!-- include start from nat-rule.xml.i -->
<tagNode name="rule">
<properties>
<help>Rule number for NAT</help>
@@ -298,4 +298,4 @@
</node>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/nat-translation-port.xml.i b/interface-definitions/include/nat-translation-port.xml.i
index a3e05316f..6e507353c 100644
--- a/interface-definitions/include/nat-translation-port.xml.i
+++ b/interface-definitions/include/nat-translation-port.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from nat-translation-port.xml.i -->
+<!-- include start from nat-translation-port.xml.i -->
<leafNode name="port">
<properties>
<help>Port number</help>
@@ -12,4 +12,4 @@
</valueHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-authentication.xml.i b/interface-definitions/include/ospf/ospf-authentication.xml.i
index efb29c1f0..322c002e4 100644
--- a/interface-definitions/include/ospf-authentication.xml.i
+++ b/interface-definitions/include/ospf/ospf-authentication.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-authentication.xml.i -->
+<!-- include start from ospf/ospf-authentication.xml.i -->
<node name="authentication">
<properties>
<help>Authentication</help>
@@ -53,4 +53,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf/ospf-common-config.xml.i b/interface-definitions/include/ospf/ospf-common-config.xml.i
new file mode 100644
index 000000000..7316af670
--- /dev/null
+++ b/interface-definitions/include/ospf/ospf-common-config.xml.i
@@ -0,0 +1,761 @@
+<!-- include start from ospf/ospf-common-config.xml.i -->
+<tagNode name="access-list">
+ <properties>
+ <help>Access list to filter networks in routing updates</help>
+ <completionHelp>
+ <path>policy access-list</path>
+ </completionHelp>
+ <valueHelp>
+ <format>u32</format>
+ <description>Access-list number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="export">
+ <properties>
+ <help>Filter for outgoing routing update [REQUIRED]</help>
+ <completionHelp>
+ <list>bgp connected kernel rip static</list>
+ </completionHelp>
+ <valueHelp>
+ <format>bgp</format>
+ <description>Filter BGP routes</description>
+ </valueHelp>
+ <valueHelp>
+ <format>connected</format>
+ <description>Filter connected routes</description>
+ </valueHelp>
+ <valueHelp>
+ <format>isis</format>
+ <description>Filter IS-IS routes</description>
+ </valueHelp>
+ <valueHelp>
+ <format>kernel</format>
+ <description>Filter Kernel routes</description>
+ </valueHelp>
+ <valueHelp>
+ <format>rip</format>
+ <description>Filter RIP routes</description>
+ </valueHelp>
+ <valueHelp>
+ <format>static</format>
+ <description>Filter static routes</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(bgp|connected|isis|kernel|rip|static)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be bgp, connected, kernel, rip, or static</constraintErrorMessage>
+ <multi/>
+ </properties>
+ </leafNode>
+ </children>
+</tagNode>
+<tagNode name="area">
+ <properties>
+ <help>OSPF Area</help>
+ <valueHelp>
+ <format>u32</format>
+ <description>OSPF area in decimal notation</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>OSPF area in dotted decimal notation</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ <validator name="ip-address"/>
+ </constraint>
+ </properties>
+ <children>
+ <node name="area-type">
+ <properties>
+ <help>Area type</help>
+ </properties>
+ <children>
+ <leafNode name="normal">
+ <properties>
+ <help>Normal OSPF area</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="nssa">
+ <properties>
+ <help>Nssa OSPF area</help>
+ </properties>
+ <children>
+ <leafNode name="default-cost">
+ <properties>
+ <help>Summary-default cost of nssa area</help>
+ <valueHelp>
+ <format>u32:0-16777215</format>
+ <description>Summary default cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777215"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="no-summary">
+ <properties>
+ <help>Do not inject inter-area routes into stub</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="translate">
+ <properties>
+ <help>Configure NSSA-ABR (default: candidate)</help>
+ <completionHelp>
+ <list>always candidate never</list>
+ </completionHelp>
+ <valueHelp>
+ <format>always</format>
+ <description>NSSA-ABR to always translate</description>
+ </valueHelp>
+ <valueHelp>
+ <format>candidate</format>
+ <description>NSSA-ABR for translate election (default)</description>
+ </valueHelp>
+ <valueHelp>
+ <format>never</format>
+ <description>NSSA-ABR to never translate</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(always|candidate|never)$</regex>
+ </constraint>
+ </properties>
+ <defaultValue>candidate</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ <node name="stub">
+ <properties>
+ <help>Stub OSPF area</help>
+ </properties>
+ <children>
+ <leafNode name="default-cost">
+ <properties>
+ <help>Summary-default cost of nssa area</help>
+ <valueHelp>
+ <format>u32:0-16777215</format>
+ <description>Summary default cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777215"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="no-summary">
+ <properties>
+ <help>Do not inject inter-area routes into stub</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <leafNode name="authentication">
+ <properties>
+ <help>OSPF area authentication type</help>
+ <completionHelp>
+ <list>plaintext-password md5</list>
+ </completionHelp>
+ <valueHelp>
+ <format>plaintext-password</format>
+ <description>Use plain-text authentication</description>
+ </valueHelp>
+ <valueHelp>
+ <format>md5</format>
+ <description>Use md5 authentication</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(plaintext-password|md5)$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="network">
+ <properties>
+ <help>OSPF network [REQUIRED]</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>OSPF network [REQUIRED]</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <tagNode name="range">
+ <properties>
+ <help>Summarize routes matching prefix (border routers only)</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>Area range prefix</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="cost">
+ <properties>
+ <help>Metric for this range</help>
+ <valueHelp>
+ <format>u32:0-16777215</format>
+ <description>Metric for this range</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777215"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="not-advertise">
+ <properties>
+ <help>Do not advertise this range</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="substitute">
+ <properties>
+ <help>Announce area range as another prefix</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>Announce area range as another prefix</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ <leafNode name="shortcut">
+ <properties>
+ <help>Area shortcut mode</help>
+ <completionHelp>
+ <list>default disable enable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Set default</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable shortcutting mode</description>
+ </valueHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable shortcutting mode</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(default|disable|enable)$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <tagNode name="virtual-link">
+ <properties>
+ <help>Virtual link</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>OSPF area in dotted decimal notation</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ <validator name="ip-address"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-authentication.xml.i>
+ #include <include/ospf/ospf-intervals.xml.i>
+ </children>
+ </tagNode>
+ </children>
+</tagNode>
+<node name="auto-cost">
+ <properties>
+ <help>Calculate OSPF interface cost according to bandwidth (default: 100)</help>
+ </properties>
+ <children>
+ <leafNode name="reference-bandwidth">
+ <properties>
+ <help>Reference bandwidth method to assign OSPF cost</help>
+ <valueHelp>
+ <format>u32:1-4294967</format>
+ <description>Reference bandwidth cost in Mbits/sec</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-4294967"/>
+ </constraint>
+ </properties>
+ <defaultValue>100</defaultValue>
+ </leafNode>
+ </children>
+</node>
+<node name="default-information">
+ <properties>
+ <help>Control distribution of default information</help>
+ </properties>
+ <children>
+ <node name="originate">
+ <properties>
+ <help>Distribute a default route</help>
+ </properties>
+ <children>
+ <leafNode name="always">
+ <properties>
+ <help>Always advertise default route</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<leafNode name="default-metric">
+ <properties>
+ <help>Metric of redistributed routes</help>
+ <valueHelp>
+ <format>u32:0-16777214</format>
+ <description>Metric of redistributed routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777214"/>
+ </constraint>
+ </properties>
+</leafNode>
+<node name="distance">
+ <properties>
+ <help>Administrative distance</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-distance-global.xml.i>
+ <node name="ospf">
+ <properties>
+ <help>OSPF administrative distance</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-distance-per-protocol.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<tagNode name="interface">
+ <properties>
+ <help>Interface related configuration</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface name</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-authentication.xml.i>
+ #include <include/ospf/ospf-intervals.xml.i>
+ #include <include/ospf/ospf-interface-common.xml.i>
+ <leafNode name="bandwidth">
+ <properties>
+ <help>Bandwidth of interface (Megabit/sec)</help>
+ <valueHelp>
+ <format>u32:1-100000</format>
+ <description>Bandwidth in Megabit/sec (for calculating OSPF cost)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-100000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="hello-multiplier">
+ <properties>
+ <help>Hello multiplier factor</help>
+ <valueHelp>
+ <format>u32:1-10</format>
+ <description>Number of Hellos to send each second</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-10"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="network">
+ <properties>
+ <help>Network type</help>
+ <completionHelp>
+ <list>broadcast non-broadcast point-to-multipoint point-to-point</list>
+ </completionHelp>
+ <valueHelp>
+ <format>broadcast</format>
+ <description>Broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>non-broadcast</format>
+ <description>Non-broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-multipoint</format>
+ <description>Point-to-multipoint network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-point</format>
+ <description>Point-to-point network type</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(broadcast|non-broadcast|point-to-multipoint|point-to-point)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ </children>
+</tagNode>
+<node name="log-adjacency-changes">
+ <properties>
+ <help>Log changes in adjacency state</help>
+ </properties>
+ <children>
+ <leafNode name="detail">
+ <properties>
+ <help>Log all state changes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="max-metric">
+ <properties>
+ <help>OSPF maximum and infinite-distance metric</help>
+ </properties>
+ <children>
+ <node name="router-lsa">
+ <properties>
+ <help>Advertise own Router-LSA with infinite distance (stub router)</help>
+ </properties>
+ <children>
+ <leafNode name="administrative">
+ <properties>
+ <help>Administratively apply, for an indefinite period</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="on-shutdown">
+ <properties>
+ <help>Advertise stub-router prior to full shutdown of OSPF</help>
+ <valueHelp>
+ <format>u32:5-100</format>
+ <description>Time (seconds) to advertise self as stub-router</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 5-100"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="on-startup">
+ <properties>
+ <help>Automatically advertise stub Router-LSA on startup of OSPF</help>
+ <valueHelp>
+ <format>u32:5-86400</format>
+ <description>Time (seconds) to advertise self as stub-router</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 5-86400"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+<node name="mpls-te">
+ <properties>
+ <help>MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters</help>
+ </properties>
+ <children>
+ <leafNode name="enable">
+ <properties>
+ <help>Enable MPLS-TE functionality</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="router-address">
+ <properties>
+ <help>Stable IP address of the advertising router</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Stable IP address of the advertising router</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ <defaultValue>0.0.0.0</defaultValue>
+ </leafNode>
+ </children>
+</node>
+<tagNode name="neighbor">
+ <properties>
+ <help>Specify neighbor router</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Neighbor IP address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ <children>
+ <leafNode name="poll-interval">
+ <properties>
+ <help>Dead neighbor polling interval (default: 60)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Seconds between dead neighbor polling interval</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>60</defaultValue>
+ </leafNode>
+ <leafNode name="priority">
+ <properties>
+ <help>Neighbor priority in seconds (default: 0)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Neighbor priority</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>0</defaultValue>
+ </leafNode>
+ </children>
+</tagNode>
+<node name="parameters">
+ <properties>
+ <help>OSPF specific parameters</help>
+ </properties>
+ <children>
+ <leafNode name="abr-type">
+ <properties>
+ <help>OSPF ABR type (default: cisco)</help>
+ <completionHelp>
+ <list>cisco ibm shortcut standard</list>
+ </completionHelp>
+ <valueHelp>
+ <format>cisco</format>
+ <description>Cisco ABR type (default)</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ibm</format>
+ <description>Ibm ABR type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>shortcut</format>
+ <description>Shortcut ABR type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>standard</format>
+ <description>Standard ABR type</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(cisco|ibm|shortcut|standard)$</regex>
+ </constraint>
+ </properties>
+ <defaultValue>cisco</defaultValue>
+ </leafNode>
+ <leafNode name="opaque-lsa">
+ <properties>
+ <help>Enable the Opaque-LSA capability (rfc2370)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="rfc1583-compatibility">
+ <properties>
+ <help>Enable rfc1583 criteria for handling AS external routes</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ #include <include/ospf/ospf-router-id.xml.i>
+ </children>
+</node>
+#include <include/routing-passive-interface-xml.i>
+<leafNode name="passive-interface-exclude">
+ <properties>
+ <help>Interface to exclude when using 'passive-interface default'</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface to exclude when suppressing routing updates</description>
+ </valueHelp>
+ <valueHelp>
+ <format>vlinkN</format>
+ <description>Virtual-link interface to exclude when suppressing routing updates</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ <regex>^(vlink[0-9]+)$</regex>
+ </constraint>
+ <multi/>
+ </properties>
+</leafNode>
+<node name="redistribute">
+ <properties>
+ <help>Redistribute information from another routing protocol</help>
+ </properties>
+ <children>
+ <node name="bgp">
+ <properties>
+ <help>Redistribute BGP routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ <node name="connected">
+ <properties>
+ <help>Redistribute connected routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ <node name="isis">
+ <properties>
+ <help>Redistribute IS-IS routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ <node name="kernel">
+ <properties>
+ <help>Redistribute kernel routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ <node name="rip">
+ <properties>
+ <help>Redistribute rip routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ <node name="static">
+ <properties>
+ <help>Redistribute static routes</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-metric.xml.i>
+ #include <include/ospf/ospf-metric-type.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<node name="refresh">
+ <properties>
+ <help>Adjust refresh parameters</help>
+ </properties>
+ <children>
+ <leafNode name="timers">
+ <properties>
+ <help>Refresh timer</help>
+ <valueHelp>
+ <format>u32:10-1800</format>
+ <description>Timer value in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 10-1800"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+#include <include/route-map.xml.i>
+<node name="timers">
+ <properties>
+ <help>Adjust routing timers</help>
+ </properties>
+ <children>
+ <node name="throttle">
+ <properties>
+ <help>Throttling adaptive timers</help>
+ </properties>
+ <children>
+ <node name="spf">
+ <properties>
+ <help>OSPF SPF timers</help>
+ </properties>
+ <children>
+ <leafNode name="delay">
+ <properties>
+ <help>Delay from first change received till SPF calculation (default: 200)</help>
+ <valueHelp>
+ <format>u32:0-600000</format>
+ <description>Delay in milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-600000"/>
+ </constraint>
+ </properties>
+ <defaultValue>200</defaultValue>
+ </leafNode>
+ <leafNode name="initial-holdtime">
+ <properties>
+ <help>Initial hold time between consecutive SPF calculations (default: 1000)</help>
+ <valueHelp>
+ <format>u32:0-600000</format>
+ <description>Initial hold time in milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-600000"/>
+ </constraint>
+ </properties>
+ <defaultValue>1000</defaultValue>
+ </leafNode>
+ <leafNode name="max-holdtime">
+ <properties>
+ <help>Maximum hold time (default: 10000)</help>
+ <valueHelp>
+ <format>u32:0-600000</format>
+ <description>Max hold time in milliseconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-600000"/>
+ </constraint>
+ </properties>
+ <defaultValue>10000</defaultValue>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/ospf/ospf-distance-global.xml.i b/interface-definitions/include/ospf/ospf-distance-global.xml.i
new file mode 100644
index 000000000..08cd76cba
--- /dev/null
+++ b/interface-definitions/include/ospf/ospf-distance-global.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from ospf/ospf-distance-global.xml.i -->
+<leafNode name="global">
+ <properties>
+ <help>Administrative distance</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Administrative distance</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/ospf/ospf-distance-per-protocol.xml.i b/interface-definitions/include/ospf/ospf-distance-per-protocol.xml.i
new file mode 100644
index 000000000..d2c4b8b52
--- /dev/null
+++ b/interface-definitions/include/ospf/ospf-distance-per-protocol.xml.i
@@ -0,0 +1,38 @@
+<!-- include start from ospf/ospf-distance-per-protocol.xml.i -->
+<leafNode name="external">
+ <properties>
+ <help>Distance for external routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for external routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+</leafNode>
+<leafNode name="inter-area">
+ <properties>
+ <help>Distance for inter-area routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for inter-area routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+</leafNode>
+<leafNode name="intra-area">
+ <properties>
+ <help>Distance for intra-area routes</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Distance for intra-area routes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-interface-common.xml.i b/interface-definitions/include/ospf/ospf-interface-common.xml.i
index c3493faa3..c0069ccb5 100644
--- a/interface-definitions/include/ospf-interface-common.xml.i
+++ b/interface-definitions/include/ospf/ospf-interface-common.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-interface-common.xml.i -->
+<!-- include start from ospf/ospf-interface-common.xml.i -->
<leafNode name="bfd">
<properties>
<help>Enable Bidirectional Forwarding Detection (BFD) support</help>
@@ -36,4 +36,4 @@
</properties>
<defaultValue>1</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-intervals.xml.i b/interface-definitions/include/ospf/ospf-intervals.xml.i
index e532bd14b..fe220eceb 100644
--- a/interface-definitions/include/ospf-intervals.xml.i
+++ b/interface-definitions/include/ospf/ospf-intervals.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-intervals.xml.i -->
+<!-- include start from ospf/ospf-intervals.xml.i -->
<leafNode name="dead-interval">
<properties>
<help>Interval after which a neighbor is declared dead (default: 40)</help>
@@ -51,4 +51,4 @@
</properties>
<defaultValue>1</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-metric-type.xml.i b/interface-definitions/include/ospf/ospf-metric-type.xml.i
index 50f11960c..1e982c4bc 100644
--- a/interface-definitions/include/ospf-metric-type.xml.i
+++ b/interface-definitions/include/ospf/ospf-metric-type.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-metric-type.xml.i -->
+<!-- include start from ospf/ospf-metric-type.xml.i -->
<leafNode name="metric-type">
<properties>
<help>OSPF metric type for default routes (default: 2)</help>
@@ -12,4 +12,4 @@
</properties>
<defaultValue>2</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-metric.xml.i b/interface-definitions/include/ospf/ospf-metric.xml.i
index 3ce12e877..125aedea7 100644
--- a/interface-definitions/include/ospf-metric.xml.i
+++ b/interface-definitions/include/ospf/ospf-metric.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-metric.xml.i -->
+<!-- include start from ospf/ospf-metric.xml.i -->
<leafNode name="metric">
<properties>
<help>OSPF default metric</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf/ospf-router-id.xml.i b/interface-definitions/include/ospf/ospf-router-id.xml.i
new file mode 100644
index 000000000..5dbb52a36
--- /dev/null
+++ b/interface-definitions/include/ospf/ospf-router-id.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from ospf/ospf-router-id.xml.i -->
+<leafNode name="router-id">
+ <properties>
+ <help>Override the default router identifier</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Override the default router identifier</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/port-number.xml.i b/interface-definitions/include/port-number.xml.i
index 81c192628..b62aef32b 100644
--- a/interface-definitions/include/port-number.xml.i
+++ b/interface-definitions/include/port-number.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from port-number.xml.i -->
+<!-- include start from port-number.xml.i -->
<leafNode name="port">
<properties>
<help>Port number used by connection</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/radius-server-ipv4-ipv6.xml.i b/interface-definitions/include/radius-server-ipv4-ipv6.xml.i
index ab3c6d72a..5b12bec62 100644
--- a/interface-definitions/include/radius-server-ipv4-ipv6.xml.i
+++ b/interface-definitions/include/radius-server-ipv4-ipv6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from radius-server-ipv4-ipv6.xml.i -->
+<!-- include start from radius-server-ipv4-ipv6.xml.i -->
<node name="radius">
<properties>
<help>RADIUS based user authentication</help>
@@ -26,7 +26,27 @@
#include <include/radius-server-port.xml.i>
</children>
</tagNode>
- #include <include/source-address-ipv4-ipv6.xml.i>
+ <leafNode name="source-address">
+ <properties>
+ <help>Source IP address used to initiate connection</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
+ </completionHelp>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 source address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 source address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ <validator name="ipv6-address"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/radius-server-ipv4.xml.i b/interface-definitions/include/radius-server-ipv4.xml.i
index 15a421b9a..ab4c8e10e 100644
--- a/interface-definitions/include/radius-server-ipv4.xml.i
+++ b/interface-definitions/include/radius-server-ipv4.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from radius-server-ipv4.xml.i -->
+<!-- include start from radius-server-ipv4.xml.i -->
<node name="radius">
<properties>
<help>RADIUS based user authentication</help>
@@ -24,4 +24,4 @@
</tagNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/radius-server-key.xml.i b/interface-definitions/include/radius-server-key.xml.i
index 32a01b402..c6301646b 100644
--- a/interface-definitions/include/radius-server-key.xml.i
+++ b/interface-definitions/include/radius-server-key.xml.i
@@ -1,7 +1,7 @@
-<!-- included start from radius-server-key.xml.i -->
+<!-- include start from radius-server-key.xml.i -->
<leafNode name="key">
<properties>
<help>Shared secret key</help>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/radius-server-port.xml.i b/interface-definitions/include/radius-server-port.xml.i
index 71b6bddb7..4e5d906bc 100644
--- a/interface-definitions/include/radius-server-port.xml.i
+++ b/interface-definitions/include/radius-server-port.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from radius-server-port.xml.i -->
+<!-- include start from radius-server-port.xml.i -->
<leafNode name="port">
<properties>
<help>Authentication port</help>
@@ -12,4 +12,4 @@
</properties>
<defaultValue>1812</defaultValue>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-access-list.xml.i b/interface-definitions/include/rip-access-list.xml.i
index 0db6863e5..9d5366a0d 100644
--- a/interface-definitions/include/rip-access-list.xml.i
+++ b/interface-definitions/include/rip-access-list.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-access-list.xml.i -->
+<!-- include start from rip-access-list.xml.i -->
<node name="access-list">
<properties>
<help>Access-list</help>
@@ -36,4 +36,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-access-list6.xml.i b/interface-definitions/include/rip-access-list6.xml.i
index 6a8a37607..a57f2038d 100644
--- a/interface-definitions/include/rip-access-list6.xml.i
+++ b/interface-definitions/include/rip-access-list6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-access-list.xml.i -->
+<!-- include start from rip-access-list.xml.i -->
<node name="access-list">
<properties>
<help>Access-list</help>
@@ -36,4 +36,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-default-information.xml.i b/interface-definitions/include/rip-default-information.xml.i
index 22a2f6ac7..9dbe744a1 100644
--- a/interface-definitions/include/rip-default-information.xml.i
+++ b/interface-definitions/include/rip-default-information.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-default-information.xml.i -->
+<!-- include start from rip-default-information.xml.i -->
<node name="default-information">
<properties>
<help>Control distribution of default route</help>
@@ -12,4 +12,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-default-metric.xml.i b/interface-definitions/include/rip-default-metric.xml.i
index a5e6016d6..e021e47dd 100644
--- a/interface-definitions/include/rip-default-metric.xml.i
+++ b/interface-definitions/include/rip-default-metric.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-default-metric.xml.i -->
+<!-- include start from rip-default-metric.xml.i -->
<leafNode name="default-metric">
<properties>
<help>Metric of redistributed routes</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-interface.xml.i b/interface-definitions/include/rip-interface.xml.i
index 6279c16c8..1807a944a 100644
--- a/interface-definitions/include/rip-interface.xml.i
+++ b/interface-definitions/include/rip-interface.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-interface.xml.i -->
+<!-- include start from rip-interface.xml.i -->
<tagNode name="interface">
<properties>
<help>Interface name</help>
@@ -35,4 +35,4 @@
</node>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-prefix-list.xml.i b/interface-definitions/include/rip-prefix-list.xml.i
index 58969a86b..ec8a34266 100644
--- a/interface-definitions/include/rip-prefix-list.xml.i
+++ b/interface-definitions/include/rip-prefix-list.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-prefix-list.xml.i -->
+<!-- include start from rip-prefix-list.xml.i -->
<node name="prefix-list">
<properties>
<help>Prefix-list</help>
@@ -30,4 +30,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-prefix-list6.xml.i b/interface-definitions/include/rip-prefix-list6.xml.i
index f73f77d05..b1026bcd2 100644
--- a/interface-definitions/include/rip-prefix-list6.xml.i
+++ b/interface-definitions/include/rip-prefix-list6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-prefix-list.xml.i -->
+<!-- include start from rip-prefix-list.xml.i -->
<node name="prefix-list">
<properties>
<help>Prefix-list</help>
@@ -30,4 +30,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/rip-redistribute.xml.i b/interface-definitions/include/rip-redistribute.xml.i
index c7b9d2c09..1e47125e9 100644
--- a/interface-definitions/include/rip-redistribute.xml.i
+++ b/interface-definitions/include/rip-redistribute.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-redistribute.xml.i -->
+<!-- include start from rip-redistribute.xml.i -->
<leafNode name="metric">
<properties>
<help>Metric for redistributed routes</help>
@@ -11,5 +11,5 @@
</constraint>
</properties>
</leafNode>
-#include <include/ospf-route-map.xml.i>
-<!-- included end -->
+#include <include/route-map.xml.i>
+<!-- include end -->
diff --git a/interface-definitions/include/rip-timers.xml.i b/interface-definitions/include/rip-timers.xml.i
index 5ba19bb06..f43ea3f5f 100644
--- a/interface-definitions/include/rip-timers.xml.i
+++ b/interface-definitions/include/rip-timers.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from rip-timers.xml.i -->
+<!-- include start from rip-timers.xml.i -->
<node name="timers">
<properties>
<help>RIPng timer values</help>
@@ -45,4 +45,4 @@
</leafNode>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/ospf-route-map.xml.i b/interface-definitions/include/route-map.xml.i
index 943a477c0..5a1c137b9 100644
--- a/interface-definitions/include/ospf-route-map.xml.i
+++ b/interface-definitions/include/route-map.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from ospf-route-map.xml.i -->
+<!-- include start from route-map.xml.i -->
<leafNode name="route-map">
<properties>
<help>Route map reference</help>
@@ -11,4 +11,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/source-address-ipv4-ipv6.xml.i b/interface-definitions/include/source-address-ipv4-ipv6.xml.i
index 4da4698c2..af3f9bb68 100644
--- a/interface-definitions/include/source-address-ipv4-ipv6.xml.i
+++ b/interface-definitions/include/source-address-ipv4-ipv6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from source-address-ipv4-ipv6.xml.i -->
+<!-- include start from source-address-ipv4-ipv6.xml.i -->
<leafNode name="source-address">
<properties>
<help>Source IP address used to initiate connection</help>
@@ -14,10 +14,8 @@
<description>IPv6 source address</description>
</valueHelp>
<constraint>
- <validator name="ipv4-address"/>
- <validator name="ipv6-address"/>
+ <validator name="ip-address"/>
</constraint>
- <multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/source-address-ipv4.xml.i b/interface-definitions/include/source-address-ipv4.xml.i
index 2dff2c65e..86235df61 100644
--- a/interface-definitions/include/source-address-ipv4.xml.i
+++ b/interface-definitions/include/source-address-ipv4.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from source-address-ipv4.xml.i -->
+<!-- include start from source-address-ipv4.xml.i -->
<leafNode name="source-address">
<properties>
<help>IPv4 source address used to initiiate connection</help>
@@ -14,4 +14,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/source-interface-ethernet.xml.i b/interface-definitions/include/source-interface-ethernet.xml.i
index d641f3cb1..ee04f2cd5 100644
--- a/interface-definitions/include/source-interface-ethernet.xml.i
+++ b/interface-definitions/include/source-interface-ethernet.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from source-interface-ethernet.xml.i -->
+<!-- include start from source-interface-ethernet.xml.i -->
<leafNode name="source-interface">
<properties>
<help>Physical interface the traffic will go through</help>
@@ -11,4 +11,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/source-interface.xml.i b/interface-definitions/include/source-interface.xml.i
index e6f0b69a1..a9c2a0f9d 100644
--- a/interface-definitions/include/source-interface.xml.i
+++ b/interface-definitions/include/source-interface.xml.i
@@ -1,14 +1,17 @@
-<!-- included start from source-interface.xml.i -->
+<!-- include start from source-interface.xml.i -->
<leafNode name="source-interface">
<properties>
- <help>Physical interface used for connection</help>
+ <help>Interface used to establish connection</help>
<valueHelp>
<format>interface</format>
- <description>Physical interface used for connection</description>
+ <description>Interface name</description>
</valueHelp>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces.py</script>
</completionHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route-blackhole.xml.i b/interface-definitions/include/static-route-blackhole.xml.i
index d0a0c2079..838a475d3 100644
--- a/interface-definitions/include/static-route-blackhole.xml.i
+++ b/interface-definitions/include/static-route-blackhole.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route-blackhole.xml.i -->
+<!-- include start from static-route-blackhole.xml.i -->
<node name="blackhole">
<properties>
<help>Silently discard packets when matched</help>
@@ -7,4 +7,4 @@
#include <include/static-route-distance.xml.i>
</children>
</node>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route-distance.xml.i b/interface-definitions/include/static-route-distance.xml.i
index d6c0d3d82..da171fe1f 100644
--- a/interface-definitions/include/static-route-distance.xml.i
+++ b/interface-definitions/include/static-route-distance.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route-distance.xml.i -->
+<!-- include start from static-route-distance.xml.i -->
<leafNode name="distance">
<properties>
<help>Distance for this route</help>
@@ -11,4 +11,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route-interface.xml.i b/interface-definitions/include/static-route-interface.xml.i
index 0f10837df..6670c0e33 100644
--- a/interface-definitions/include/static-route-interface.xml.i
+++ b/interface-definitions/include/static-route-interface.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route-interface.xml.i -->
+<!-- include start from static-route-interface.xml.i -->
<leafNode name="interface">
<properties>
<help>Gateway interface name</help>
@@ -14,4 +14,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route-map.xml.i b/interface-definitions/include/static-route-map.xml.i
index 25542b8b1..48f5055aa 100644
--- a/interface-definitions/include/static-route-map.xml.i
+++ b/interface-definitions/include/static-route-map.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route-map.xml.i -->
+<!-- include start from static-route-map.xml.i -->
<leafNode name="route-map">
<properties>
<help>Filter routes installed in local route map</help>
@@ -7,4 +7,4 @@
</completionHelp>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route-vrf.xml.i b/interface-definitions/include/static-route-vrf.xml.i
index 70f8b0be8..eda4d7aee 100644
--- a/interface-definitions/include/static-route-vrf.xml.i
+++ b/interface-definitions/include/static-route-vrf.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route-vrf.xml.i -->
+<!-- include start from static-route-vrf.xml.i -->
<leafNode name="vrf">
<properties>
<help>VRF to leak route</help>
@@ -16,4 +16,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route.xml.i b/interface-definitions/include/static-route.xml.i
index 386582e09..94fbdd3d6 100644
--- a/interface-definitions/include/static-route.xml.i
+++ b/interface-definitions/include/static-route.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route.xml.i -->
+<!-- include start from static-route.xml.i -->
<tagNode name="route">
<properties>
<help>VRF static IPv4 route</help>
@@ -31,6 +31,21 @@
</leafNode>
</children>
</node>
+ <leafNode name="dhcp-interface">
+ <properties>
+ <help>DHCP interface supplying next-hop IP address</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>DHCP interface name</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
+ </properties>
+ </leafNode>
<tagNode name="interface">
<properties>
<help>Next-hop IPv4 router interface</help>
@@ -71,5 +86,5 @@
</tagNode>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/static-route6.xml.i b/interface-definitions/include/static-route6.xml.i
index fcf97cd03..4522ef39b 100644
--- a/interface-definitions/include/static-route6.xml.i
+++ b/interface-definitions/include/static-route6.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from static-route6.xml.i -->
+<!-- include start from static-route6.xml.i -->
<tagNode name="route6">
<properties>
<help>VRF static IPv6 route</help>
@@ -71,5 +71,5 @@
</tagNode>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/tunnel-local-remote-ip.xml.i b/interface-definitions/include/tunnel-local-remote-ip.xml.i
deleted file mode 100644
index 85c20f482..000000000
--- a/interface-definitions/include/tunnel-local-remote-ip.xml.i
+++ /dev/null
@@ -1,37 +0,0 @@
-<!-- included start from tunnel-local-remote-ip.xml.i -->
-<leafNode name="local-ip">
- <properties>
- <help>Local IP address for this tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Local IPv4 address for this tunnel</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>Local IPv6 address for this tunnel</description>
- </valueHelp>
- <completionHelp>
- <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
- </completionHelp>
- <constraint>
- <validator name="ip-address"/>
- </constraint>
- </properties>
-</leafNode>
-<leafNode name="remote-ip">
- <properties>
- <help>Remote IP address for this tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Remote IPv4 address for this tunnel</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>Remote IPv6 address for this tunnel</description>
- </valueHelp>
- <constraint>
- <!-- does it need fixing/changing to be more restrictive ? -->
- <validator name="ip-address"/>
- </constraint>
- </properties>
-</leafNode>
diff --git a/interface-definitions/include/tunnel-parameters-ip.xml.i b/interface-definitions/include/tunnel-parameters-ip.xml.i
deleted file mode 100644
index 0a667d199..000000000
--- a/interface-definitions/include/tunnel-parameters-ip.xml.i
+++ /dev/null
@@ -1,46 +0,0 @@
-<!-- included start from tunnel-parameters-ip.xml.i -->
-<leafNode name="ttl">
- <properties>
- <help>Time to live (default: 0)</help>
- <valueHelp>
- <format>0</format>
- <description>Copy value from original IP header</description>
- </valueHelp>
- <valueHelp>
- <format>1-255</format>
- <description>Time to Live</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- <constraintErrorMessage>TTL must be between 0 and 255</constraintErrorMessage>
- </properties>
- <defaultValue>0</defaultValue>
-</leafNode>
-<leafNode name="tos">
- <properties>
- <help>Type of Service (TOS)</help>
- <valueHelp>
- <format>0-99</format>
- <description>Type of Service (TOS)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-99"/>
- </constraint>
- <constraintErrorMessage>TOS must be between 0 and 99</constraintErrorMessage>
- </properties>
- <defaultValue>inherit</defaultValue>
-</leafNode>
-<leafNode name="key">
- <properties>
- <help>Tunnel key</help>
- <valueHelp>
- <format>u32</format>
- <description>Tunnel key</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- <constraintErrorMessage>key must be between 0-4294967295</constraintErrorMessage>
- </properties>
-</leafNode>
diff --git a/interface-definitions/include/tunnel-remote.xml.i b/interface-definitions/include/tunnel-remote.xml.i
new file mode 100644
index 000000000..324d100d4
--- /dev/null
+++ b/interface-definitions/include/tunnel-remote.xml.i
@@ -0,0 +1,18 @@
+<!-- include start from tunnel-remote.xml.i -->
+<leafNode name="remote">
+ <properties>
+ <help>Tunnel remote address</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Tunnel remote IPv4 address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>Tunnel remote IPv6 address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ip-address"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/vif-s.xml.i b/interface-definitions/include/vif-s.xml.i
index 01cb59efc..5760bb000 100644
--- a/interface-definitions/include/vif-s.xml.i
+++ b/interface-definitions/include/vif-s.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from vif-s.xml.i -->
+<!-- include start from vif-s.xml.i -->
<tagNode name="vif-s">
<properties>
<help>QinQ TAG-S Virtual Local Area Network (VLAN) ID</help>
@@ -64,4 +64,4 @@
#include <include/interface-vrf.xml.i>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/vif.xml.i b/interface-definitions/include/vif.xml.i
index bc60dd04d..0f09b993d 100644
--- a/interface-definitions/include/vif.xml.i
+++ b/interface-definitions/include/vif.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from vif.xml.i -->
+<!-- include start from vif.xml.i -->
<tagNode name="vif">
<properties>
<help>Virtual Local Area Network (VLAN) ID</help>
@@ -49,4 +49,4 @@
#include <include/interface-mtu-68-16000.xml.i>
</children>
</tagNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/vni.xml.i b/interface-definitions/include/vni.xml.i
new file mode 100644
index 000000000..faff4c3c3
--- /dev/null
+++ b/interface-definitions/include/vni.xml.i
@@ -0,0 +1,12 @@
+ <leafNode name="vni">
+ <properties>
+ <help>Virtual Network Identifier</help>
+ <valueHelp>
+ <format>0-16777214</format>
+ <description>VXLAN virtual network identifier</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777214"/>
+ </constraint>
+ </properties>
+ </leafNode>
diff --git a/interface-definitions/include/vpn-ipsec-encryption.xml.i b/interface-definitions/include/vpn-ipsec-encryption.xml.i
index 1c1d728fc..041ba9902 100644
--- a/interface-definitions/include/vpn-ipsec-encryption.xml.i
+++ b/interface-definitions/include/vpn-ipsec-encryption.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from vpn-ipsec-encryption.xml.i -->
+<!-- include start from vpn-ipsec-encryption.xml.i -->
<leafNode name="encryption">
<properties>
<help>Encryption algorithm</help>
@@ -230,4 +230,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/vpn-ipsec-hash.xml.i b/interface-definitions/include/vpn-ipsec-hash.xml.i
index ca5976d27..93d57b622 100644
--- a/interface-definitions/include/vpn-ipsec-hash.xml.i
+++ b/interface-definitions/include/vpn-ipsec-hash.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from pn-ipsec-hash.xml.i -->
+<!-- include start from pn-ipsec-hash.xml.i -->
<leafNode name="hash">
<properties>
<help>Hash algorithm</help>
@@ -62,4 +62,4 @@
</constraint>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/include/webproxy-url-filtering.xml.i b/interface-definitions/include/webproxy-url-filtering.xml.i
index 07db0948f..265bbff94 100644
--- a/interface-definitions/include/webproxy-url-filtering.xml.i
+++ b/interface-definitions/include/webproxy-url-filtering.xml.i
@@ -1,4 +1,4 @@
-<!-- included start from webproxy-url-filtering.xml.i -->
+<!-- include start from webproxy-url-filtering.xml.i -->
<leafNode name="allow-category">
<properties>
<help>Category to allow</help>
@@ -116,4 +116,4 @@
<multi/>
</properties>
</leafNode>
-<!-- included end -->
+<!-- include end -->
diff --git a/interface-definitions/interfaces-erspan.xml.in b/interface-definitions/interfaces-erspan.xml.in
index 8a4bfea2b..2394d3534 100644
--- a/interface-definitions/interfaces-erspan.xml.in
+++ b/interface-definitions/interfaces-erspan.xml.in
@@ -20,7 +20,8 @@
#include <include/interface-disable.xml.i>
#include <include/interface-disable-link-detect.xml.i>
#include <include/interface-mtu-64-8024.xml.i>
- #include <include/tunnel-local-remote-ip.xml.i>
+ #include <include/source-address-ipv4-ipv6.xml.i>
+ #include <include/tunnel-remote.xml.i>
<leafNode name="encapsulation">
<properties>
<help>Encapsulation of this tunnel interface</help>
@@ -51,7 +52,9 @@
<help>IPv4 specific tunnel parameters</help>
</properties>
<children>
- #include <include/tunnel-parameters-ip.xml.i>
+ #include <include/interface-parameters-key.xml.i>
+ #include <include/interface-parameters-tos.xml.i>
+ #include <include/interface-parameters-ttl.xml.i>
</children>
</node>
<leafNode name="version">
diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in
index 0c776e3c3..25308c8ef 100644
--- a/interface-definitions/interfaces-geneve.xml.in
+++ b/interface-definitions/interfaces-geneve.xml.in
@@ -23,30 +23,33 @@
#include <include/interface-ipv6-options.xml.i>
#include <include/interface-mac.xml.i>
#include <include/interface-mtu-1450-16000.xml.i>
- <leafNode name="remote">
+ <node name="parameters">
<properties>
- <help>Remote address of GENEVE tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Remote address of GENEVE tunnel</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
+ <help>GENEVE tunnel parameters</help>
</properties>
- </leafNode>
- <leafNode name="vni">
- <properties>
- <help>Virtual Network Identifier</help>
- <valueHelp>
- <format>0-16777214</format>
- <description>GENEVE virtual network identifier</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777214"/>
- </constraint>
- </properties>
- </leafNode>
+ <children>
+ <node name="ip">
+ <properties>
+ <help>IPv4 specific tunnel parameters</help>
+ </properties>
+ <children>
+ #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">
+ <properties>
+ <help>IPv6 specific tunnel parameters</help>
+ </properties>
+ <children>
+ #include <include/interface-parameters-flowlabel.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ #include <include/tunnel-remote.xml.i>
+ #include <include/vni.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in
index 3853cd339..68ac15861 100644
--- a/interface-definitions/interfaces-l2tpv3.xml.in
+++ b/interface-definitions/interfaces-l2tpv3.xml.in
@@ -55,22 +55,7 @@
</leafNode>
#include <include/interface-ipv4-options.xml.i>
#include <include/interface-ipv6-options.xml.i>
- <leafNode name="local-ip">
- <properties>
- <help>Local IP address for L2TPv3 tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Local IPv4 address of tunnel</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>Local IPv6 address of tunnel</description>
- </valueHelp>
- <constraint>
- <validator name="ip-address"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/source-address-ipv4-ipv6.xml.i>
#include <include/interface-mtu-68-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1488</defaultValue>
@@ -99,22 +84,8 @@
</constraint>
</properties>
</leafNode>
- <leafNode name="remote-ip">
- <properties>
- <help>Remote IP address for L2TPv3 tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Remote IPv4 address of tunnel</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>Remote IPv6 address of tunnel</description>
- </valueHelp>
- <constraint>
- <validator name="ip-address"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/interface-mtu-68-16000.xml.i>
+ #include <include/tunnel-remote.xml.i>
<leafNode name="session-id">
<properties>
<help>Session identifier</help>
diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in
index 94d78c6dd..3f2e5bb69 100644
--- a/interface-definitions/interfaces-macsec.xml.in
+++ b/interface-definitions/interfaces-macsec.xml.in
@@ -28,14 +28,18 @@
<properties>
<help>Cipher suite used</help>
<completionHelp>
- <list>gcm-aes-128</list>
+ <list>gcm-aes-128 gcm-aes-256</list>
</completionHelp>
<valueHelp>
<format>gcm-aes-128</format>
<description>Galois/Counter Mode of AES cipher with 128-bit key (default)</description>
</valueHelp>
+ <valueHelp>
+ <format>gcm-aes-256</format>
+ <description>Galois/Counter Mode of AES cipher with 256-bit key</description>
+ </valueHelp>
<constraint>
- <regex>(gcm-aes-128)</regex>
+ <regex>^(gcm-aes-128|gcm-aes-256)$</regex>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in
index 45573a826..c169d877d 100644
--- a/interface-definitions/interfaces-tunnel.xml.in
+++ b/interface-definitions/interfaces-tunnel.xml.in
@@ -27,7 +27,8 @@
</leafNode>
#include <include/interface-ipv4-options.xml.i>
#include <include/interface-ipv6-options.xml.i>
- #include <include/tunnel-local-remote-ip.xml.i>
+ #include <include/source-address-ipv4-ipv6.xml.i>
+ #include <include/tunnel-remote.xml.i>
<leafNode name="source-interface">
<properties>
<help>Physical Interface used for underlaying traffic</help>
@@ -79,21 +80,25 @@
<properties>
<help>Encapsulation of this tunnel interface</help>
<completionHelp>
- <list>gre gre-bridge ip6gre ip6ip6 ipip ipip6 sit</list>
+ <list>gre gretap ip6gre ip6gretap ip6ip6 ipip ipip6 sit</list>
</completionHelp>
<valueHelp>
<format>gre</format>
<description>Generic Routing Encapsulation</description>
</valueHelp>
<valueHelp>
- <format>gre-bridge</format>
- <description>Generic Routing Encapsulation bridge interface</description>
+ <format>gretap</format>
+ <description>Generic Routing Encapsulation (virtual L2 tunnel)</description>
</valueHelp>
<valueHelp>
<format>ip6gre</format>
<description>GRE over IPv6 network</description>
</valueHelp>
<valueHelp>
+ <format>ip6gretap</format>
+ <description>Generic Routing Encapsulation over IPv6 (virtual L2 tunnel)</description>
+ </valueHelp>
+ <valueHelp>
<format>ip6ip6</format>
<description>IP6 in IP6 encapsulation</description>
</valueHelp>
@@ -110,9 +115,9 @@
<description>Simple Internet Transition encapsulation</description>
</valueHelp>
<constraint>
- <regex>^(gre|gre-bridge|ip6gre|ip6ip6|ipip|ipip6|sit)$</regex>
+ <regex>^(gre|gretap|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)$</regex>
</constraint>
- <constraintErrorMessage>Invalid encapsulation, must be one of: gre, gre-bridge, ipip, sit, ipip6, ip6ip6, ip6gre</constraintErrorMessage>
+ <constraintErrorMessage>Invalid encapsulation, must be one of: gre, gretap, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6</constraintErrorMessage>
</properties>
</leafNode>
<leafNode name="multicast">
@@ -151,7 +156,9 @@
<valueless/>
</properties>
</leafNode>
- #include <include/tunnel-parameters-ip.xml.i>
+ #include <include/interface-parameters-key.xml.i>
+ #include <include/interface-parameters-tos.xml.i>
+ #include <include/interface-parameters-ttl.xml.i>
</children>
</node>
<node name="ipv6">
@@ -161,32 +168,27 @@
<children>
<leafNode name="encaplimit">
<properties>
- <help>Encaplimit field</help>
+ <help>Set fixed encapsulation limit</help>
+ <completionHelp>
+ <list>none</list>
+ </completionHelp>
<valueHelp>
<format>0-255</format>
<description>Encaplimit (default: 4)</description>
</valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- <constraintErrorMessage>key must be between 0-255</constraintErrorMessage>
- </properties>
- <defaultValue>4</defaultValue>
- </leafNode>
- <leafNode name="flowlabel">
- <properties>
- <help>Flowlabel</help>
<valueHelp>
- <format>0x0-0x0FFFFF</format>
- <description>Tunnel key, 'inherit' or hex value</description>
+ <format>none</format>
+ <description>Encaplimit disabled</description>
</valueHelp>
<constraint>
- <regex>(0x){0,1}(0?[0-9A-Fa-f]{1,5})</regex>
+ <regex>^(none)$</regex>
+ <validator name="numeric" argument="--range 0-255"/>
</constraint>
- <constraintErrorMessage>Must be 'inherit' or a number</constraintErrorMessage>
+ <constraintErrorMessage>Tunnel encaplimit must be 0-255 or none</constraintErrorMessage>
</properties>
- <defaultValue>inherit</defaultValue>
+ <defaultValue>4</defaultValue>
</leafNode>
+ #include <include/interface-parameters-flowlabel.xml.i>
<leafNode name="hoplimit">
<properties>
<help>Hoplimit</help>
diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in
index f90a86274..97a40a9dc 100644
--- a/interface-definitions/interfaces-vxlan.xml.in
+++ b/interface-definitions/interfaces-vxlan.xml.in
@@ -37,29 +37,45 @@
</leafNode>
#include <include/interface-ipv4-options.xml.i>
#include <include/interface-ipv6-options.xml.i>
- #include <include/source-address-ipv4.xml.i>
- #include <include/source-interface.xml.i>
#include <include/interface-mac.xml.i>
#include <include/interface-mtu-1200-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1450</defaultValue>
</leafNode>
- <leafNode name="remote">
+ <node name="parameters">
<properties>
- <help>Remote address of VXLAN tunnel</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Remote IPv4 address of VXLAN tunnel</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>Remote IPv6 address of VXLAN tunnel</description>
- </valueHelp>
- <constraint>
- <validator name="ip-address"/>
- </constraint>
+ <help>VXLAN tunnel parameters</help>
</properties>
- </leafNode>
+ <children>
+ <node name="ip">
+ <properties>
+ <help>IPv4 specific tunnel parameters</help>
+ </properties>
+ <children>
+ #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>
+ </children>
+ </node>
+ <node name="ipv6">
+ <properties>
+ <help>IPv6 specific tunnel parameters</help>
+ </properties>
+ <children>
+ #include <include/interface-parameters-flowlabel.xml.i>
+ </children>
+ </node>
+ <leafNode name="nolearning">
+ <properties>
+ <help>Do not add unknown addresses into forwarding database</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
<leafNode name="port">
<properties>
<help>Destination port of VXLAN tunnel (default: 8472)</help>
@@ -73,18 +89,10 @@
</properties>
<defaultValue>8472</defaultValue>
</leafNode>
- <leafNode name="vni">
- <properties>
- <help>Virtual Network Identifier</help>
- <valueHelp>
- <format>0-16777214</format>
- <description>VXLAN virtual network identifier</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777214"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/source-address-ipv4-ipv6.xml.i>
+ #include <include/source-interface.xml.i>
+ #include <include/tunnel-remote.xml.i>
+ #include <include/vni.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in
index b45ebc0a8..d5e1226f9 100644
--- a/interface-definitions/nat66.xml.in
+++ b/interface-definitions/nat66.xml.in
@@ -70,18 +70,31 @@
</node>
<node name="translation">
<properties>
- <help>Translated IPv6 prefix options</help>
+ <help>Translated IPv6 address options</help>
</properties>
<children>
- <leafNode name="prefix">
+ <leafNode name="address">
<properties>
- <help>IPv6 prefix to translate to</help>
+ <help>IPv6 address to translate to</help>
+ <completionHelp>
+ <list>masquerade</list>
+ </completionHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 address</description>
+ </valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 prefix</description>
</valueHelp>
+ <valueHelp>
+ <format>masquerade</format>
+ <description>NAT to the primary address of outbound-interface</description>
+ </valueHelp>
<constraint>
+ <validator name="ipv6-address"/>
<validator name="ipv6-prefix"/>
+ <regex>(masquerade)</regex>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/protocols-bfd.xml.in b/interface-definitions/protocols-bfd.xml.in
index 8900e7955..cc3c3bf12 100644
--- a/interface-definitions/protocols-bfd.xml.in
+++ b/interface-definitions/protocols-bfd.xml.in
@@ -11,7 +11,7 @@
<children>
<tagNode name="peer">
<properties>
- <help>Configures a new BFD peer to listen and talk to</help>
+ <help>Configures BFD peer to listen and talk to</help>
<valueHelp>
<format>ipv4</format>
<description>BFD peer IPv4 address</description>
@@ -26,6 +26,18 @@
</constraint>
</properties>
<children>
+ <leafNode name="profile">
+ <properties>
+ <help>Use settings from BFD profile</help>
+ <completionHelp>
+ <path>protocols bfd profile</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>BFD profile name</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
<node name="source">
<properties>
<help>Bind listener to specified interface/address, mandatory for IPv6</help>
@@ -42,6 +54,9 @@
<leafNode name="address">
<properties>
<help>Local address to bind our peer listener to</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_local_ips.sh --both</script>
+ </completionHelp>
<valueHelp>
<format>ipv4</format>
<description>Local IPv4 address used to connect to the peer</description>
@@ -58,79 +73,28 @@
</leafNode>
</children>
</node>
- <node name="interval">
- <properties>
- <help>Configure timer intervals</help>
- </properties>
- <children>
- <leafNode name="receive">
- <properties>
- <help>Minimum interval of receiving control packets</help>
- <valueHelp>
- <format>10-60000</format>
- <description>Interval in milliseconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 10-60000"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="transmit">
- <properties>
- <help>Minimum interval of transmitting control packets</help>
- <valueHelp>
- <format>10-60000</format>
- <description>Interval in milliseconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 10-60000"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="multiplier">
- <properties>
- <help>Multiplier to determine packet loss</help>
- <valueHelp>
- <format>2-255</format>
- <description>Remote transmission interval will be multiplied by this value</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 2-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="echo-interval">
- <properties>
- <help>Echo receive transmission interval</help>
- <valueHelp>
- <format>10-60000</format>
- <description>The minimal echo receive transmission interval that this system is capable of handling</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 10-60000"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="shutdown">
- <properties>
- <help>Disable this peer</help>
- <valueless/>
- </properties>
- </leafNode>
+ #include <include/bfd-common.xml.i>
<leafNode name="multihop">
<properties>
<help>Allow this BFD peer to not be directly connected</help>
<valueless/>
</properties>
</leafNode>
- <leafNode name="echo-mode">
- <properties>
- <help>Enables the echo transmission mode</help>
- <valueless/>
- </properties>
- </leafNode>
+ </children>
+ </tagNode>
+ <tagNode name="profile">
+ <properties>
+ <help>Configure BFD profile used by individual peer</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of BFD profile</description>
+ </valueHelp>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9]{1,32}$</regex>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bfd-common.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/protocols-bgp.xml.in b/interface-definitions/protocols-bgp.xml.in
index 4af53acdc..cf897d04f 100644
--- a/interface-definitions/protocols-bgp.xml.in
+++ b/interface-definitions/protocols-bgp.xml.in
@@ -1,914 +1,21 @@
<?xml version="1.0"?>
-<!-- Border Gateway Protocol (BGP) configuration -->
<interfaceDefinition>
<node name="protocols">
<children>
<tagNode name="bgp" owner="${vyos_conf_scripts_dir}/protocols_bgp.py">
<properties>
<help>Border Gateway Protocol (BGP)</help>
+ <priority>820</priority>
<valueHelp>
<format>u32:1-4294967294</format>
- <description>AS number</description>
+ <description>Autonomous System Number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4294967294"/>
</constraint>
- <priority>820</priority>
</properties>
<children>
- <node name="address-family">
- <properties>
- <help>BGP address-family parameters</help>
- </properties>
- <children>
- <node name="ipv4-unicast">
- <properties>
- <help>IPv4 BGP settings</help>
- </properties>
- <children>
- <tagNode name="aggregate-address">
- <properties>
- <help>BGP aggregate network</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>BGP aggregate network</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- </properties>
- <children>
- #include <include/bgp-afi-aggregate-address.xml.i>
- </children>
- </tagNode>
- <tagNode name="network">
- <properties>
- <help>BGP network</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>BGP network</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- </properties>
- <children>
- <leafNode name="backdoor">
- <properties>
- <help>Network as a backdoor route</help>
- <valueless/>
- </properties>
- </leafNode>
- #include <include/bgp-route-map.xml.i>
- </children>
- </tagNode>
- <node name="redistribute">
- <properties>
- <help>Redistribute routes from other protocols into BGP</help>
- </properties>
- <children>
- <node name="connected">
- <properties>
- <help>Redistribute connected routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="kernel">
- <properties>
- <help>Redistribute kernel routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="ospf">
- <properties>
- <help>Redistribute OSPF routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="rip">
- <properties>
- <help>Redistribute RIP routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="static">
- <properties>
- <help>Redistribute static routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <leafNode name="table">
- <properties>
- <help>Redistribute non-main Kernel Routing Table</help>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <node name="ipv6-unicast">
- <properties>
- <help>IPv6 BGP settings</help>
- </properties>
- <children>
- <tagNode name="aggregate-address">
- <properties>
- <help>BGP aggregate network</help>
- <valueHelp>
- <format>ipv6net</format>
- <description>Aggregate network</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-prefix"/>
- </constraint>
- </properties>
- <children>
- #include <include/bgp-afi-aggregate-address.xml.i>
- </children>
- </tagNode>
- <tagNode name="network">
- <properties>
- <help>BGP network</help>
- <valueHelp>
- <format>ipv6net</format>
- <description>Aggregate network</description>
- </valueHelp>
- <constraint>
- <validator name="ipv6-prefix"/>
- </constraint>
- </properties>
- <children>
- <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-route-map.xml.i>
- </children>
- </tagNode>
- <node name="redistribute">
- <properties>
- <help>Redistribute routes from other protocols into BGP</help>
- </properties>
- <children>
- <node name="connected">
- <properties>
- <help>Redistribute connected routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="kernel">
- <properties>
- <help>Redistribute kernel routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="ospfv3">
- <properties>
- <help>Redistribute OSPFv3 routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="ripng">
- <properties>
- <help>Redistribute RIPng routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <node name="static">
- <properties>
- <help>Redistribute static routes into BGP</help>
- </properties>
- <children>
- #include <include/bgp-afi-redistribute-metric-route-map.xml.i>
- </children>
- </node>
- <leafNode name="table">
- <properties>
- <help>Redistribute non-main Kernel Routing Table</help>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <node name="l2vpn-evpn">
- <properties>
- <help>L2VPN EVPN BGP settings</help>
- </properties>
- <children>
- <leafNode name="advertise-all-vni">
- <properties>
- <help>Advertise All local VNIs</help>
- <valueless/>
- </properties>
- </leafNode>
- #include <include/bgp-afi-l2vpn-common.xml.i>
- <leafNode name="advertise-pip">
- <properties>
- <help>EVPN system primary IP</help>
- <valueHelp>
- <format>ipv4</format>
- <description>IP address</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="rt-auto-derive">
- <properties>
- <help>Auto derivation of Route Target (RFC8365)</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="flooding">
- <properties>
- <help>Specify handling for BUM packets</help>
- </properties>
- <children>
- <leafNode name="disable">
- <properties>
- <help>Do not flood any BUM packets</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="head-end-replication">
- <properties>
- <help>Flood BUM packets using head-end replication</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="rd">
- <properties>
- <help>Route Distinguisher</help>
- <valueHelp>
- <format>txt</format>
- <description>Route Distinguisher, asn:xxx</description>
- </valueHelp>
- <constraint>
- <regex>^[0-9]{1,10}:[0-9]{1,5}$</regex>
- </constraint>
- </properties>
- </leafNode>
- <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>
- <tagNode name="vni">
- <properties>
- <help>VXLAN Network Identifier</help>
- <valueHelp>
- <format>u32:1-16777215</format>
- <description>VNI number</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-16777215"/>
- </constraint>
- </properties>
- <children>
- #include <include/bgp-afi-l2vpn-common.xml.i>
- </children>
- </tagNode>
- </children>
- </node>
- </children>
- </node>
- <node name="maximum-paths">
- <properties>
- <help>BGP multipaths</help>
- </properties>
- <children>
- <leafNode name="ebgp">
- <properties>
- <help>Maximum ebgp multipaths</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>EBGP multipaths</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="ibgp">
- <properties>
- <help>Maximum ibgp multipaths</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>EBGP multipaths</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <node name="listen">
- <properties>
- <help>Listen for and accept BGP dynamic neighbors from range</help>
- </properties>
- <children>
- <leafNode name="limit">
- <properties>
- <help>Maximum number of dynamic neighbors that can be created</help>
- <valueHelp>
- <format>u32:1-5000</format>
- <description>BGP neighbor limit</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-5000"/>
- </constraint>
- </properties>
- </leafNode>
- <tagNode name="range">
- <properties>
- <help>BGP dynamic neighbors listen range</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>IPv4 dynamic neighbors listen range</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6net</format>
- <description>IPv6 dynamic neighbors listen range</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- <validator name="ipv6-prefix"/>
- </constraint>
- </properties>
- <children>
- #include <include/bgp-peer-group.xml.i>
- </children>
- </tagNode>
- </children>
- </node>
- <tagNode name="neighbor">
- <properties>
- <help>BGP neighbor</help>
- <valueHelp>
- <format>ipv4</format>
- <description>BGP neighbor IP address</description>
- </valueHelp>
- <valueHelp>
- <format>ipv6</format>
- <description>BGP neighbor IPv6 address</description>
- </valueHelp>
- <valueHelp>
- <format>txt</format>
- <description>Interface name</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- <validator name="ipv6-address"/>
- <validator name="interface-name"/>
- </constraint>
- </properties>
- <children>
- <node name="address-family">
- <properties>
- <help>Parameters relating to IPv4 or IPv6 routes</help>
- </properties>
- <children>
- #include <include/bgp-neighbor-afi-ipv4-unicast.xml.i>
- #include <include/bgp-neighbor-afi-ipv6-unicast.xml.i>
- #include <include/bgp-neighbor-afi-l2vpn-evpn.xml.i>
- </children>
- </node>
- <leafNode name="advertisement-interval">
- <properties>
- <help>Minimum interval for sending routing updates</help>
- <valueHelp>
- <format>u32:0-600</format>
- <description>Advertisement interval in seconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-600"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/bgp-bfd.xml.i>
- #include <include/bgp-capability.xml.i>
- #include <include/bgp-description.xml.i>
- #include <include/bgp-disable-capability-negotiation.xml.i>
- #include <include/bgp-disable-connected-check.xml.i>
- #include <include/bgp-ebgp-multihop.xml.i>
- <node name="interface">
- <properties>
- <help>Interface parameters</help>
- </properties>
- <children>
- #include <include/bgp-peer-group.xml.i>
- #include <include/bgp-remote-as.xml.i>
- <node name="v6only">
- <properties>
- <help>Enable BGP with v6 link-local only</help>
- </properties>
- <children>
- #include <include/bgp-peer-group.xml.i>
- #include <include/bgp-remote-as.xml.i>
- </children>
- </node>
- </children>
- </node>
- #include <include/bgp-local-as.xml.i>
- #include <include/bgp-override-capability.xml.i>
- #include <include/bgp-passive.xml.i>
- #include <include/bgp-password.xml.i>
- #include <include/bgp-peer-group.xml.i>
- <leafNode name="port">
- <properties>
- <help>Neighbor BGP port</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Neighbor BGP port number</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/bgp-remote-as.xml.i>
- #include <include/bgp-shutdown.xml.i>
- <leafNode name="strict-capability-match">
- <properties>
- <help>Enable strict capability negotiation</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="timers">
- <properties>
- <help>Neighbor timers</help>
- </properties>
- <children>
- <leafNode name="connect">
- <properties>
- <help>BGP connect timer for this neighbor</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Connect timer in seconds</description>
- </valueHelp>
- <valueHelp>
- <format>0</format>
- <description>Disable connect timer</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-65535"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/bgp-timers-holdtime.xml.i>
- #include <include/bgp-timers-keepalive.xml.i>
- </children>
- </node>
- #include <include/bgp-ttl-security.xml.i>
- #include <include/bgp-update-source.xml.i>
- </children>
- </tagNode>
- <node name="parameters">
- <properties>
- <help>BGP parameters</help>
- </properties>
- <children>
- <leafNode name="always-compare-med">
- <properties>
- <help>Always compare MEDs from different neighbors</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="bestpath">
- <properties>
- <help>Default bestpath selection mechanism</help>
- </properties>
- <children>
- <node name="as-path">
- <properties>
- <help>AS-path attribute comparison parameters</help>
- </properties>
- <children>
- <leafNode name="confed">
- <properties>
- <help>Compare AS-path lengths including confederation sets and sequences</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="ignore">
- <properties>
- <help>Ignore AS-path length in selecting a route</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="multipath-relax">
- <properties>
- <help>Allow load sharing across routes that have different AS paths (but same length)</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="compare-routerid">
- <properties>
- <help>Compare the router-id for identical EBGP paths</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="med">
- <properties>
- <help>MED attribute comparison parameters</help>
- </properties>
- <children>
- <leafNode name="confed">
- <properties>
- <help>Compare MEDs among confederation paths</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="missing-as-worst">
- <properties>
- <help>Treat missing route as a MED as the least preferred one</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <leafNode name="cluster-id">
- <properties>
- <help>Route-reflector cluster-id</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Route-reflector cluster-id</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- </leafNode>
- <node name="confederation">
- <properties>
- <help>AS confederation parameters</help>
- </properties>
- <children>
- <leafNode name="identifier">
- <properties>
- <help>Confederation AS identifier [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-4294967294</format>
- <description>Confederation AS id</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-4294967294"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="peers">
- <properties>
- <help>Peer ASs in the BGP confederation</help>
- <valueHelp>
- <format>u32:1-4294967294</format>
- <description>Peer AS number</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-4294967294"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <node name="dampening">
- <properties>
- <help>Enable route-flap dampening</help>
- </properties>
- <children>
- <leafNode name="half-life">
- <properties>
- <help>Half-life time for dampening [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-45</format>
- <description>Half-life penalty in minutes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-45"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="max-suppress-time">
- <properties>
- <help>Maximum duration to suppress a stable route [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Maximum suppress duration in minutes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="re-use">
- <properties>
- <help>Threshold to start reusing a route [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-20000</format>
- <description>Re-use penalty points</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-20000"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="start-suppress-time">
- <properties>
- <help>When to start suppressing a route [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-20000</format>
- <description>Start-suppress penalty points</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-20000"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <node name="default">
- <properties>
- <help>BGP defaults</help>
- </properties>
- <children>
- <leafNode name="local-pref">
- <properties>
- <help>Default local preference</help>
- <valueHelp>
- <format>u32</format>
- <description>Local preference</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="no-ipv4-unicast">
- <properties>
- <help>Deactivate IPv4 unicast for a peer by default</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="deterministic-med">
- <properties>
- <help>Compare MEDs between different peers in the same AS</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="distance">
- <properties>
- <help>Administratives distances for BGP routes</help>
- </properties>
- <children>
- <node name="global">
- <properties>
- <help>Global administratives distances for BGP routes</help>
- </properties>
- <children>
- <leafNode name="external">
- <properties>
- <help>Administrative distance for external BGP routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance for external BGP routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="internal">
- <properties>
- <help>Administrative distance for internal BGP routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance for internal BGP routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="local">
- <properties>
- <help>Administrative distance for local BGP routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance for internal BGP routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <tagNode name="prefix">
- <properties>
- <help>Administrative distance for a specific BGP prefix</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>Administrative distance for a specific BGP prefix</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- </properties>
- <children>
- <leafNode name="distance">
- <properties>
- <help>Administrative distance for prefix</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance for external BGP routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
- <node name="graceful-restart">
- <properties>
- <help>Graceful restart capability parameters</help>
- </properties>
- <children>
- <leafNode name="stalepath-time">
- <properties>
- <help>Maximum time to hold onto restarting neighbors stale paths</help>
- <valueHelp>
- <format>u32:1-3600</format>
- <description>Hold time in seconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-3600"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="graceful-shutdown">
- <properties>
- <help>Graceful shutdown</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="log-neighbor-changes">
- <properties>
- <help>Log neighbor up/down changes and reset reason</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="network-import-check">
- <properties>
- <help>Enable IGP route check for network statements</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="no-client-to-client-reflection">
- <properties>
- <help>Disable client to client route reflection</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="no-fast-external-failover">
- <properties>
- <help>Disable immediate session reset on peer link down event</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="router-id">
- <properties>
- <help>BGP router id</help>
- <valueHelp>
- <format>ipv4</format>
- <description>BGP router id</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- <tagNode name="peer-group">
- <properties>
- <help>BGP peer-group</help>
- </properties>
- <children>
- <node name="address-family">
- <properties>
- <help>BGP peer-group address-family parameters</help>
- </properties>
- <children>
- #include <include/bgp-neighbor-afi-ipv4-unicast.xml.i>
- #include <include/bgp-neighbor-afi-ipv6-unicast.xml.i>
- #include <include/bgp-neighbor-afi-l2vpn-evpn.xml.i>
- </children>
- </node>
- #include <include/bgp-bfd.xml.i>
- #include <include/bgp-capability.xml.i>
- #include <include/bgp-description.xml.i>
- #include <include/bgp-disable-capability-negotiation.xml.i>
- #include <include/bgp-disable-connected-check.xml.i>
- #include <include/bgp-ebgp-multihop.xml.i>
- #include <include/bgp-local-as.xml.i>
- #include <include/bgp-override-capability.xml.i>
- #include <include/bgp-passive.xml.i>
- #include <include/bgp-password.xml.i>
- #include <include/bgp-remote-as.xml.i>
- #include <include/bgp-shutdown.xml.i>
- #include <include/bgp-ttl-security.xml.i>
- #include <include/bgp-update-source.xml.i>
- </children>
- </tagNode>
- #include <include/bgp-route-map.xml.i>
- <node name="timers">
- <properties>
- <help>BGP protocol timers</help>
- </properties>
- <children>
- #include <include/bgp-timers-holdtime.xml.i>
- #include <include/bgp-timers-keepalive.xml.i>
- </children>
- </node>
+ #include <include/bgp/bgp-common-config.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/protocols-ospf.xml.in b/interface-definitions/protocols-ospf.xml.in
index d0cfa14b1..d9c3325ec 100644
--- a/interface-definitions/protocols-ospf.xml.in
+++ b/interface-definitions/protocols-ospf.xml.in
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Protocol OSPF configuration -->
<interfaceDefinition>
<node name="protocols">
<children>
@@ -9,803 +8,7 @@
<priority>620</priority>
</properties>
<children>
- <tagNode name="access-list">
- <properties>
- <help>Access list to filter networks in routing updates</help>
- <completionHelp>
- <path>policy access-list</path>
- </completionHelp>
- <valueHelp>
- <format>u32</format>
- <description>Access-list number</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- </constraint>
- </properties>
- <children>
- <leafNode name="export">
- <properties>
- <help>Filter for outgoing routing update [REQUIRED]</help>
- <completionHelp>
- <list>bgp connected kernel rip static</list>
- </completionHelp>
- <valueHelp>
- <format>bgp</format>
- <description>Filter BGP routes</description>
- </valueHelp>
- <valueHelp>
- <format>connected</format>
- <description>Filter connected routes</description>
- </valueHelp>
- <valueHelp>
- <format>kernel</format>
- <description>Filter Kernel routes</description>
- </valueHelp>
- <valueHelp>
- <format>rip</format>
- <description>Filter RIP routes</description>
- </valueHelp>
- <valueHelp>
- <format>static</format>
- <description>Filter static routes</description>
- </valueHelp>
- <constraint>
- <regex>^(bgp|connected|kernel|rip|static)$</regex>
- </constraint>
- <constraintErrorMessage>Must be bgp, connected, kernel, rip, or static</constraintErrorMessage>
- <multi/>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- <tagNode name="area">
- <properties>
- <help>OSPF Area</help>
- <valueHelp>
- <format>u32</format>
- <description>OSPF area in decimal notation</description>
- </valueHelp>
- <valueHelp>
- <format>ipv4</format>
- <description>OSPF area in dotted decimal notation</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- <validator name="ip-address"/>
- </constraint>
- </properties>
- <children>
- <node name="area-type">
- <properties>
- <help>Area type</help>
- </properties>
- <children>
- <leafNode name="normal">
- <properties>
- <help>Normal OSPF area</help>
- <valueless/>
- </properties>
- </leafNode>
- <node name="nssa">
- <properties>
- <help>Nssa OSPF area</help>
- </properties>
- <children>
- <leafNode name="default-cost">
- <properties>
- <help>Summary-default cost of nssa area</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>Summary default cost</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="no-summary">
- <properties>
- <help>Do not inject inter-area routes into stub</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="translate">
- <properties>
- <help>Configure NSSA-ABR (default: candidate)</help>
- <completionHelp>
- <list>always candidate never</list>
- </completionHelp>
- <valueHelp>
- <format>always</format>
- <description>NSSA-ABR to always translate</description>
- </valueHelp>
- <valueHelp>
- <format>candidate</format>
- <description>NSSA-ABR for translate election (default)</description>
- </valueHelp>
- <valueHelp>
- <format>never</format>
- <description>NSSA-ABR to never translate</description>
- </valueHelp>
- <constraint>
- <regex>^(always|candidate|never)$</regex>
- </constraint>
- </properties>
- <defaultValue>candidate</defaultValue>
- </leafNode>
- </children>
- </node>
- <node name="stub">
- <properties>
- <help>Stub OSPF area</help>
- </properties>
- <children>
- <leafNode name="default-cost">
- <properties>
- <help>Summary-default cost of nssa area</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>Summary default cost</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="no-summary">
- <properties>
- <help>Do not inject inter-area routes into stub</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <leafNode name="authentication">
- <properties>
- <help>OSPF area authentication type</help>
- <completionHelp>
- <list>plaintext-password md5</list>
- </completionHelp>
- <valueHelp>
- <format>plaintext-password</format>
- <description>Use plain-text authentication</description>
- </valueHelp>
- <valueHelp>
- <format>md5</format>
- <description>Use md5 authentication</description>
- </valueHelp>
- <constraint>
- <regex>^(plaintext-password|md5)$</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="network">
- <properties>
- <help>OSPF network [REQUIRED]</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>OSPF network [REQUIRED]</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
- <tagNode name="range">
- <properties>
- <help>Summarize routes matching prefix (border routers only)</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>Area range prefix</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- </properties>
- <children>
- <leafNode name="cost">
- <properties>
- <help>Metric for this range</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>Metric for this range</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="not-advertise">
- <properties>
- <help>Do not advertise this range</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="substitute">
- <properties>
- <help>Announce area range as another prefix</help>
- <valueHelp>
- <format>ipv4net</format>
- <description>Announce area range as another prefix</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-prefix"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- <leafNode name="shortcut">
- <properties>
- <help>Area shortcut mode</help>
- <completionHelp>
- <list>default disable enable</list>
- </completionHelp>
- <valueHelp>
- <format>default</format>
- <description>Set default</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable shortcutting mode</description>
- </valueHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable shortcutting mode</description>
- </valueHelp>
- <constraint>
- <regex>^(default|disable|enable)$</regex>
- </constraint>
- </properties>
- </leafNode>
- <tagNode name="virtual-link">
- <properties>
- <help>Virtual link</help>
- <valueHelp>
- <format>ipv4</format>
- <description>OSPF area in dotted decimal notation</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-4294967295"/>
- <validator name="ip-address"/>
- </constraint>
- </properties>
- <children>
- #include <include/ospf-authentication.xml.i>
- #include <include/ospf-intervals.xml.i>
- </children>
- </tagNode>
- </children>
- </tagNode>
- <node name="auto-cost">
- <properties>
- <help>Calculate OSPF interface cost according to bandwidth (default: 100)</help>
- </properties>
- <children>
- <leafNode name="reference-bandwidth">
- <properties>
- <help>Reference bandwidth method to assign OSPF cost</help>
- <valueHelp>
- <format>u32:1-4294967</format>
- <description>Reference bandwidth cost in Mbits/sec</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-4294967"/>
- </constraint>
- </properties>
- <defaultValue>100</defaultValue>
- </leafNode>
- </children>
- </node>
- <node name="default-information">
- <properties>
- <help>Control distribution of default information</help>
- </properties>
- <children>
- <node name="originate">
- <properties>
- <help>Distribute a default route</help>
- </properties>
- <children>
- <leafNode name="always">
- <properties>
- <help>Always advertise default route</help>
- <valueless/>
- </properties>
- </leafNode>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- </children>
- </node>
- <leafNode name="default-metric">
- <properties>
- <help>Metric of redistributed routes</help>
- <valueHelp>
- <format>u32:0-16777214</format>
- <description>Metric of redistributed routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777214"/>
- </constraint>
- </properties>
- </leafNode>
- <node name="distance">
- <properties>
- <help>Administrative distance</help>
- </properties>
- <children>
- <leafNode name="global">
- <properties>
- <help>OSPF administrative distance</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <node name="ospf">
- <properties>
- <help>OSPF administrative distance</help>
- </properties>
- <children>
- <leafNode name="external">
- <properties>
- <help>Distance for external routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for external routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="inter-area">
- <properties>
- <help>Distance for inter-area routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for inter-area routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="intra-area">
- <properties>
- <help>Distance for intra-area routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for intra-area routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <tagNode name="interface">
- <properties>
- <help>Interface related configuration</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
- </completionHelp>
- <valueHelp>
- <format>txt</format>
- <description>Interface name</description>
- </valueHelp>
- <constraint>
- <validator name="interface-name"/>
- </constraint>
- </properties>
- <children>
- #include <include/ospf-authentication.xml.i>
- #include <include/ospf-intervals.xml.i>
- #include <include/ospf-interface-common.xml.i>
- <leafNode name="bandwidth">
- <properties>
- <help>Bandwidth of interface (Megabit/sec)</help>
- <valueHelp>
- <format>u32:1-100000</format>
- <description>Bandwidth in Megabit/sec (for calculating OSPF cost)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-100000"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="hello-multiplier">
- <properties>
- <help>Hello multiplier factor</help>
- <valueHelp>
- <format>u32:1-10</format>
- <description>Number of Hellos to send each second</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-10"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="network">
- <properties>
- <help>Network type</help>
- <completionHelp>
- <list>broadcast non-broadcast point-to-multipoint point-to-point</list>
- </completionHelp>
- <valueHelp>
- <format>broadcast</format>
- <description>Broadcast network type</description>
- </valueHelp>
- <valueHelp>
- <format>non-broadcast</format>
- <description>Non-broadcast network type</description>
- </valueHelp>
- <valueHelp>
- <format>point-to-multipoint</format>
- <description>Point-to-multipoint network type</description>
- </valueHelp>
- <valueHelp>
- <format>point-to-point</format>
- <description>Point-to-point network type</description>
- </valueHelp>
- <constraint>
- <regex>^(broadcast|non-broadcast|point-to-multipoint|point-to-point)$</regex>
- </constraint>
- <constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- <node name="log-adjacency-changes">
- <properties>
- <help>Log changes in adjacency state</help>
- </properties>
- <children>
- <leafNode name="detail">
- <properties>
- <help>Log all state changes</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </node>
- <node name="max-metric">
- <properties>
- <help>OSPF maximum and infinite-distance metric</help>
- </properties>
- <children>
- <node name="router-lsa">
- <properties>
- <help>Advertise own Router-LSA with infinite distance (stub router)</help>
- </properties>
- <children>
- <leafNode name="administrative">
- <properties>
- <help>Administratively apply, for an indefinite period</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="on-shutdown">
- <properties>
- <help>Advertise stub-router prior to full shutdown of OSPF</help>
- <valueHelp>
- <format>u32:5-100</format>
- <description>Time (seconds) to advertise self as stub-router</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 5-100"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="on-startup">
- <properties>
- <help>Automatically advertise stub Router-LSA on startup of OSPF</help>
- <valueHelp>
- <format>u32:5-86400</format>
- <description>Time (seconds) to advertise self as stub-router</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 5-86400"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <node name="mpls-te">
- <properties>
- <help>MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters</help>
- </properties>
- <children>
- <leafNode name="enable">
- <properties>
- <help>Enable MPLS-TE functionality</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="router-address">
- <properties>
- <help>Stable IP address of the advertising router</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Stable IP address of the advertising router</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- <defaultValue>0.0.0.0</defaultValue>
- </leafNode>
- </children>
- </node>
- <tagNode name="neighbor">
- <properties>
- <help>Specify neighbor router</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Neighbor IP address</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- <children>
- <leafNode name="poll-interval">
- <properties>
- <help>Dead neighbor polling interval (default: 60)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Seconds between dead neighbor polling interval</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>60</defaultValue>
- </leafNode>
- <leafNode name="priority">
- <properties>
- <help>Neighbor priority in seconds (default: 0)</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>Neighbor priority</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- <defaultValue>0</defaultValue>
- </leafNode>
- </children>
- </tagNode>
- <node name="parameters">
- <properties>
- <help>OSPF specific parameters</help>
- </properties>
- <children>
- <leafNode name="abr-type">
- <properties>
- <help>OSPF ABR type (default: cisco)</help>
- <completionHelp>
- <list>cisco ibm shortcut standard</list>
- </completionHelp>
- <valueHelp>
- <format>cisco</format>
- <description>Cisco ABR type (default)</description>
- </valueHelp>
- <valueHelp>
- <format>ibm</format>
- <description>Ibm ABR type</description>
- </valueHelp>
- <valueHelp>
- <format>shortcut</format>
- <description>Shortcut ABR type</description>
- </valueHelp>
- <valueHelp>
- <format>standard</format>
- <description>Standard ABR type</description>
- </valueHelp>
- <constraint>
- <regex>^(cisco|ibm|shortcut|standard)$</regex>
- </constraint>
- </properties>
- <defaultValue>cisco</defaultValue>
- </leafNode>
- <leafNode name="opaque-lsa">
- <properties>
- <help>Enable the Opaque-LSA capability (rfc2370)</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="rfc1583-compatibility">
- <properties>
- <help>Enable rfc1583 criteria for handling AS external routes</help>
- <valueless/>
- </properties>
- </leafNode>
- <leafNode name="router-id">
- <properties>
- <help>Override the default router identifier</help>
- <valueHelp>
- <format>ipv4</format>
- <description>Override the default router identifier</description>
- </valueHelp>
- <constraint>
- <validator name="ipv4-address"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- #include <include/routing-passive-interface-xml.i>
- <leafNode name="passive-interface-exclude">
- <properties>
- <help>Interface to exclude when using 'passive-interface default'</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
- </completionHelp>
- <valueHelp>
- <format>txt</format>
- <description>Interface to be passive (i.e. suppress routing updates)</description>
- </valueHelp>
- <constraint>
- <validator name="interface-name"/>
- </constraint>
- <multi/>
- </properties>
- </leafNode>
- <node name="redistribute">
- <properties>
- <help>Redistribute information from another routing protocol</help>
- </properties>
- <children>
- <node name="bgp">
- <properties>
- <help>Redistribute BGP routes</help>
- </properties>
- <children>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- <node name="connected">
- <properties>
- <help>Redistribute connected routes</help>
- </properties>
- <children>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- <node name="kernel">
- <properties>
- <help>Redistribute kernel routes</help>
- </properties>
- <children>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- <node name="rip">
- <properties>
- <help>Redistribute rip routes</help>
- </properties>
- <children>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- <node name="static">
- <properties>
- <help>Redistribute static routes</help>
- </properties>
- <children>
- #include <include/ospf-metric.xml.i>
- #include <include/ospf-metric-type.xml.i>
- #include <include/ospf-route-map.xml.i>
- </children>
- </node>
- </children>
- </node>
- <node name="refresh">
- <properties>
- <help>Adjust refresh parameters</help>
- </properties>
- <children>
- <leafNode name="timers">
- <properties>
- <help>Refresh timer</help>
- <valueHelp>
- <format>u32:10-1800</format>
- <description>Timer value in seconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 10-1800"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </node>
- #include <include/ospf-route-map.xml.i>
- <node name="timers">
- <properties>
- <help>Adjust routing timers</help>
- </properties>
- <children>
- <node name="throttle">
- <properties>
- <help>Throttling adaptive timers</help>
- </properties>
- <children>
- <node name="spf">
- <properties>
- <help>OSPF SPF timers</help>
- </properties>
- <children>
- <leafNode name="delay">
- <properties>
- <help>Delay from first change received till SPF calculation (default: 200)</help>
- <valueHelp>
- <format>u32:0-600000</format>
- <description>Delay in milliseconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-600000"/>
- </constraint>
- </properties>
- <defaultValue>200</defaultValue>
- </leafNode>
- <leafNode name="initial-holdtime">
- <properties>
- <help>Initial hold time between consecutive SPF calculations (default: 1000)</help>
- <valueHelp>
- <format>u32:0-600000</format>
- <description>Initial hold time in milliseconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-600000"/>
- </constraint>
- </properties>
- <defaultValue>1000</defaultValue>
- </leafNode>
- <leafNode name="max-holdtime">
- <properties>
- <help>Maximum hold time (default: 10000)</help>
- <valueHelp>
- <format>u32:0-600000</format>
- <description>Max hold time in milliseconds</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-600000"/>
- </constraint>
- </properties>
- <defaultValue>10000</defaultValue>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- </children>
- </node>
+ #include <include/ospf/ospf-common-config.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/protocols-ospfv3.xml.in b/interface-definitions/protocols-ospfv3.xml.in
index e28faa3cf..06787b604 100644
--- a/interface-definitions/protocols-ospfv3.xml.in
+++ b/interface-definitions/protocols-ospfv3.xml.in
@@ -41,7 +41,7 @@
</completionHelp>
</properties>
</leafNode>
- <tagNode name="interface">
+ <leafNode name="interface">
<properties>
<help>Enable routing on an IPv6 interface</help>
<completionHelp>
@@ -54,63 +54,9 @@
<constraint>
<validator name="interface-name"/>
</constraint>
+ <multi/>
</properties>
- <children>
- #include <include/ospf-intervals.xml.i>
- #include <include/ospf-interface-common.xml.i>
- <leafNode name="ifmtu">
- <properties>
- <help>Interface MTU</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Interface MTU</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="instance-id">
- <properties>
- <help>Instance Id (default: 0)</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>Instance Id</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- <defaultValue>0</defaultValue>
- </leafNode>
- <leafNode name="network">
- <properties>
- <help>Network type</help>
- <completionHelp>
- <list>broadcast point-to-point</list>
- </completionHelp>
- <valueHelp>
- <format>broadcast</format>
- <description>Broadcast network type</description>
- </valueHelp>
- <valueHelp>
- <format>point-to-point</format>
- <description>Point-to-point network type</description>
- </valueHelp>
- <constraint>
- <regex>^(broadcast|point-to-point)$</regex>
- </constraint>
- <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="passive">
- <properties>
- <help>Disable forming of adjacency</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </tagNode>
+ </leafNode>
<tagNode name="range">
<properties>
<help>Specify IPv6 prefix (border routers only)</help>
@@ -144,80 +90,93 @@
<help>Administrative distance</help>
</properties>
<children>
- <leafNode name="global">
- <properties>
- <help>OSPFv3 administrative distance</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Administrative distance</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/ospf/ospf-distance-global.xml.i>
<node name="ospfv3">
<properties>
<help>OSPFv3 administrative distance</help>
</properties>
<children>
- <leafNode name="external">
- <properties>
- <help>Distance for external routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for external routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="inter-area">
- <properties>
- <help>Distance for inter-area routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for inter-area routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="intra-area">
- <properties>
- <help>Distance for intra-area routes</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>Distance for intra-area routes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-255"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/ospf/ospf-distance-per-protocol.xml.i>
</children>
</node>
</children>
</node>
- <node name="parameters">
+ <tagNode name="interface">
<properties>
- <help>OSPFv3 specific parameters</help>
+ <help>Enable routing on an IPv6 interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface used for routing information exchange</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
</properties>
<children>
- <leafNode name="router-id">
+ #include <include/ospf/ospf-intervals.xml.i>
+ #include <include/ospf/ospf-interface-common.xml.i>
+ <leafNode name="ifmtu">
+ <properties>
+ <help>Interface MTU</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Interface MTU</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="instance-id">
+ <properties>
+ <help>Instance Id (default: 0)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Instance Id</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>0</defaultValue>
+ </leafNode>
+ <leafNode name="network">
<properties>
- <help>Override the default router identifier</help>
+ <help>Network type</help>
+ <completionHelp>
+ <list>broadcast point-to-point</list>
+ </completionHelp>
<valueHelp>
- <format>ipv4</format>
- <description>Override the default router identifier</description>
+ <format>broadcast</format>
+ <description>Broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-point</format>
+ <description>Point-to-point network type</description>
</valueHelp>
<constraint>
- <validator name="ipv4-address"/>
+ <regex>^(broadcast|point-to-point)$</regex>
</constraint>
+ <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage>
</properties>
</leafNode>
+ <leafNode name="passive">
+ <properties>
+ <help>Disable forming of adjacency</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ <node name="parameters">
+ <properties>
+ <help>OSPFv3 specific parameters</help>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-router-id.xml.i>
</children>
</node>
<node name="redistribute">
@@ -230,7 +189,7 @@
<help>Redistribute BGP routes</help>
</properties>
<children>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
<node name="connected">
@@ -238,7 +197,7 @@
<help>Redistribute connected routes</help>
</properties>
<children>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
<node name="kernel">
@@ -246,7 +205,7 @@
<help>Redistribute kernel routes</help>
</properties>
<children>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
<node name="ripng">
@@ -254,7 +213,7 @@
<help>Redistribute RIPNG routes</help>
</properties>
<children>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
<node name="static">
@@ -262,12 +221,12 @@
<help>Redistribute static routes</help>
</properties>
<children>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
</children>
</node>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in
index 263350dc8..1ae3bd8f7 100644
--- a/interface-definitions/protocols-rip.xml.in
+++ b/interface-definitions/protocols-rip.xml.in
@@ -176,6 +176,14 @@
#include <include/rip-redistribute.xml.i>
</children>
</node>
+ <node name="isis">
+ <properties>
+ <help>Redistribute IS-IS routes</help>
+ </properties>
+ <children>
+ #include <include/rip-redistribute.xml.i>
+ </children>
+ </node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes</help>
diff --git a/interface-definitions/protocols-ripng.xml.in b/interface-definitions/protocols-ripng.xml.in
index e456c3f3b..3eac27788 100644
--- a/interface-definitions/protocols-ripng.xml.in
+++ b/interface-definitions/protocols-ripng.xml.in
@@ -137,7 +137,7 @@
<multi/>
</properties>
</leafNode>
- #include <include/ospf-route-map.xml.i>
+ #include <include/route-map.xml.i>
#include <include/rip-timers.xml.i>
</children>
</node>
diff --git a/interface-definitions/protocols-vrf.xml.in b/interface-definitions/protocols-vrf.xml.in
deleted file mode 100644
index 81942d124..000000000
--- a/interface-definitions/protocols-vrf.xml.in
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<interfaceDefinition>
- <node name="protocols">
- <children>
- <tagNode name="vrf" owner="${vyos_conf_scripts_dir}/protocols_vrf.py">
- <properties>
- <help>Name of VRF to add route for</help>
- <completionHelp>
- <path>vrf name</path>
- </completionHelp>
- <valueHelp>
- <format>txt</format>
- <description>VRF instance name</description>
- </valueHelp>
- <constraint>
- <validator name="vrf-name"/>
- </constraint>
- <constraintErrorMessage>VRF instance name must be 15 characters or less and can not\nbe named as regular network interfaces.\n</constraintErrorMessage>
- </properties>
- <children>
- <node name="static">
- <properties>
- <help>Static route parameters</help>
- </properties>
- <children>
- #include <include/static-route.xml.i>
- #include <include/static-route6.xml.i>
- </children>
- </node>
- </children>
- </tagNode>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/interface-definitions/service_console-server.xml.in b/interface-definitions/service_console-server.xml.in
index 59a9fe237..293ee1ba5 100644
--- a/interface-definitions/service_console-server.xml.in
+++ b/interface-definitions/service_console-server.xml.in
@@ -5,7 +5,6 @@
<node name="console-server" owner="${vyos_conf_scripts_dir}/service_console-server.py">
<properties>
<help>Serial Console Server</help>
- <priority>990</priority>
</properties>
<children>
<tagNode name="device">
@@ -13,7 +12,7 @@
<help>System serial interface name (ttyS or ttyUSB)</help>
<completionHelp>
<script>ls -1 /dev | grep ttyS</script>
- <script>ls -1 /dev/serial/by-bus</script>
+ <script>if [ -d /dev/serial/by-bus ]; then ls -1 /dev/serial/by-bus; fi</script>
</completionHelp>
<valueHelp>
<format>ttySxxx</format>
@@ -36,7 +35,7 @@
<list>300 1200 2400 4800 9600 19200 38400 57600 115200</list>
</completionHelp>
<constraint>
- <regex>(300|1200|2400|4800|9600|19200|38400|57600|115200)</regex>
+ <regex>^(300|1200|2400|4800|9600|19200|38400|57600|115200)$</regex>
</constraint>
</properties>
</leafNode>
@@ -47,7 +46,7 @@
<list>7 8</list>
</completionHelp>
<constraint>
- <regex>(7|8)</regex>
+ <validator name="numeric" argument="--range 7-8"/>
</constraint>
</properties>
<defaultValue>8</defaultValue>
@@ -59,7 +58,7 @@
<list>1 2</list>
</completionHelp>
<constraint>
- <regex>(1|2)</regex>
+ <validator name="numeric" argument="--range 1-2"/>
</constraint>
</properties>
<defaultValue>1</defaultValue>
@@ -71,7 +70,7 @@
<list>even odd none</list>
</completionHelp>
<constraint>
- <regex>(even|odd|none)</regex>
+ <regex>^(even|odd|none)$</regex>
</constraint>
</properties>
<defaultValue>none</defaultValue>
diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in
index eca9e75a7..b1d25926e 100644
--- a/interface-definitions/vrf.xml.in
+++ b/interface-definitions/vrf.xml.in
@@ -15,17 +15,61 @@
</leafNode>
<tagNode name="name">
<properties>
- <help>VRF instance name</help>
+ <help>Virtual Routing and Forwarding instance</help>
<constraint>
<validator name="vrf-name"/>
</constraint>
<constraintErrorMessage>VRF instance name must be 15 characters or less and can not\nbe named as regular network interfaces.\n</constraintErrorMessage>
<valueHelp>
<format>txt</format>
- <description>Instance name</description>
+ <description>VRF instance name</description>
</valueHelp>
</properties>
<children>
+ #include <include/interface-description.xml.i>
+ #include <include/interface-disable.xml.i>
+ <node name="protocols">
+ <properties>
+ <help>Routing protocol parameters</help>
+ </properties>
+ <children>
+ <node name="static" owner="${vyos_conf_scripts_dir}/protocols_static.py $VAR(../../@)">
+ <properties>
+ <help>Static route parameters</help>
+ <priority>600</priority>
+ </properties>
+ <children>
+ #include <include/static-route.xml.i>
+ #include <include/static-route6.xml.i>
+ </children>
+ </node>
+ <tagNode name="bgp" owner="${vyos_conf_scripts_dir}/protocols_bgp.py $VAR(../../@)">
+ <properties>
+ <help>Border Gateway Protocol (BGP)</help>
+ <priority>820</priority>
+ <valueHelp>
+ <format>u32:1-4294967294</format>
+ <description>Autonomous System Number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-4294967294"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/bgp/bgp-common-config.xml.i>
+ </children>
+ </tagNode>
+ <node name="ospf" owner="${vyos_conf_scripts_dir}/protocols_ospf.py $VAR(../../@)">
+ <properties>
+ <help>Open Shortest Path First (OSPF)</help>
+ <priority>620</priority>
+ </properties>
+ <children>
+ #include <include/ospf/ospf-common-config.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
<leafNode name="table">
<properties>
<help>Routing table associated with this instance</help>
@@ -39,8 +83,6 @@
<constraintErrorMessage>VRF routing table must be in range from 100 to 2147483647</constraintErrorMessage>
</properties>
</leafNode>
- #include <include/interface-description.xml.i>
- #include <include/interface-disable.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/vrrp.xml.in b/interface-definitions/vrrp.xml.in
index caa9f4a33..3c4c9b83c 100644
--- a/interface-definitions/vrrp.xml.in
+++ b/interface-definitions/vrrp.xml.in
@@ -212,6 +212,15 @@
</constraint>
</properties>
</leafNode>
+ <leafNode name="mode-force">
+ <properties>
+ <valueless/>
+ <help>Disable VRRP state checking (deprecated, will be removed in VyOS 1.4)</help>
+ <constraint>
+ <validator name="script"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
</node>
<leafNode name="virtual-address">
diff --git a/op-mode-definitions/include/bgp-afi-common.xml.i b/op-mode-definitions/include/bgp-afi-common.xml.i
new file mode 100644
index 000000000..06cfc42a5
--- /dev/null
+++ b/op-mode-definitions/include/bgp-afi-common.xml.i
@@ -0,0 +1,40 @@
+<!-- included start from bgp-afi-common.xml.i -->
+<tagNode name="community">
+ <properties>
+ <help>Community number where AA and NN are (0-65535)</help>
+ <completionHelp>
+ <list>AA:NN</list>
+ </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>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<tagNode name="large-community">
+ <properties>
+ <help>List of large-community numbers</help>
+ <completionHelp>
+ <list>AA:BB:CC</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<leafNode name="statistics">
+ <properties>
+ <help>RIB advertisement statistics</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<leafNode name="summary">
+ <properties>
+ <help>Summary of BGP neighbor status</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<!-- included end -->
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
new file mode 100644
index 000000000..dc0926375
--- /dev/null
+++ b/op-mode-definitions/include/bgp-afi-ipv4-ipv6-common.xml.i
@@ -0,0 +1,243 @@
+<!-- included start from bgp-afi-ipv4-ipv6-common.xml.i -->
+<node name="community">
+ <properties>
+ <help>Display routes matching the community</help>
+ </properties>
+ <children>
+ <leafNode name="accept-own">
+ <properties>
+ <help>Should accept local VPN route if exported and imported into different VRF (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="accept-own-nexthop">
+ <properties>
+ <help>Should accept VPN route with local nexthop (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="blackhole">
+ <properties>
+ <help>Inform EBGP peers to blackhole traffic to prefix (well-known community)</help>
+ </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>
+ <leafNode name="graceful-shutdown">
+ <properties>
+ <help>Graceful shutdown (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="llgr-stale">
+ <properties>
+ <help>Staled Long-lived Graceful Restart VPN route (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="local-AS">
+ <properties>
+ <help>Do not send outside local AS (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="no-advertise">
+ <properties>
+ <help>Do not advertise to any peer (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="no-export">
+ <properties>
+ <help>Do not export to next AS (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="no-llgr">
+ <properties>
+ <help>Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="no-peer">
+ <properties>
+ <help>Do not export to any peer (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="route-filter-translated-v4">
+ <properties>
+ <help>RT translated VPNv4 route filtering (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="route-filter-translated-v6">
+ <properties>
+ <help>RT translated VPNv6 route filtering (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="route-filter-v4">
+ <properties>
+ <help>RT VPNv4 route filtering (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="route-filter-v6">
+ <properties>
+ <help>RT VPNv6 route filtering (well-known community)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</node>
+<tagNode name="community-list">
+ <properties>
+ <help>Display routes matching the community-list</help>
+ <completionHelp>
+ <list>1-500 name</list>
+ </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>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<node name="dampening">
+ <properties>
+ <help>Display detailed information about dampening</help>
+ </properties>
+ <children>
+ <leafNode name="dampened-paths">
+ <properties>
+ <help>Display paths suppressed due to dampening</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="flap-statistics">
+ <properties>
+ <help>Display flap statistics of routes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="parameters">
+ <properties>
+ <help>Display detail of configured dampening parameters</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+</node>
+<tagNode name="filter-list">
+ <properties>
+ <help>Display routes conforming to the filter-list</help>
+ <completionHelp>
+ <script>vtysh -c 'show bgp as-path-access-list' | grep 'AS path access list' | awk '{print $NF}'</script>
+ </completionHelp>
+ </properties>
+</tagNode>
+<node name="large-community">
+ <properties>
+ <help>Show BGP routes matching the specified large-communities</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</node>
+<leafNode name="neighbors">
+ <properties>
+ <help>Detailed information on TCP and BGP neighbor connections</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<tagNode name="neighbors">
+ <properties>
+ <help>Show detailed BGP IPv4 unicast neighbor information</help>
+ <completionHelp>
+ <script>vtysh -c 'show bgp summary' | awk '{print $1'} | grep -e '^[0-9a-f]'</script>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ <leafNode name="advertised-routes">
+ <properties>
+ <help>Show routes advertised to a BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="dampened-routes">
+ <properties>
+ <help>Show dampened routes received from BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="flap-statistics">
+ <properties>
+ <help>Show flap statistics of the routes learned from BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="prefix-counts">
+ <properties>
+ <help>Show detailed prefix count information for BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <node name="received">
+ <properties>
+ <help>Show information received from BGP neighbor</help>
+ </properties>
+ <children>
+ <leafNode name="prefix-filter">
+ <properties>
+ <help>Show prefixlist filter</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="received-routes">
+ <properties>
+ <help>Show received routes from BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="routes">
+ <properties>
+ <help>Show routes learned from BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+</tagNode>
+<tagNode name="prefix-list">
+ <properties>
+ <help>Display routes conforming to the prefix-list</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<tagNode name="regexp">
+ <properties>
+ <help>Display routes matching the AS path regular expression</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<tagNode name="route-map">
+ <properties>
+ <help>Show BGP routes matching the specified route map</help>
+ <completionHelp>
+ <path>policy route-map</path>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<!-- included end -->
diff --git a/op-mode-definitions/include/bgp-prefix-bestpath-multipath.xml.i b/op-mode-definitions/include/bgp-prefix-bestpath-multipath.xml.i
new file mode 100644
index 000000000..224fa6b45
--- /dev/null
+++ b/op-mode-definitions/include/bgp-prefix-bestpath-multipath.xml.i
@@ -0,0 +1,20 @@
+<!-- included start from bgp-prefix-bestpath-multipath.xml.i -->
+<leafNode name="bestpath">
+ <properties>
+ <help>Display only the bestpath</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<leafNode name="multipath">
+ <properties>
+ <help>Display only multipaths</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<leafNode name="longer-prefixes">
+ <properties>
+ <help>Display route and more specific routes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<!-- included end -->
diff --git a/op-mode-definitions/include/vni-tagnode-all.xml.i b/op-mode-definitions/include/vni-tagnode-all.xml.i
new file mode 100644
index 000000000..0fedb9371
--- /dev/null
+++ b/op-mode-definitions/include/vni-tagnode-all.xml.i
@@ -0,0 +1,11 @@
+<!-- included start from vni-tagnode-all.xml.i -->
+<tagNode name="vni">
+ <properties>
+ <help>VXLAN network identifier (VNI) number</help>
+ <completionHelp>
+ <list>1-16777215 all</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<!-- included end -->
diff --git a/op-mode-definitions/include/vni-tagnode.xml.i b/op-mode-definitions/include/vni-tagnode.xml.i
new file mode 100644
index 000000000..22f2d33bd
--- /dev/null
+++ b/op-mode-definitions/include/vni-tagnode.xml.i
@@ -0,0 +1,11 @@
+<!-- included start from vni-tagnode.xml.i -->
+<tagNode name="vni">
+ <properties>
+ <help>VXLAN network identifier (VNI) number</help>
+ <completionHelp>
+ <list>1-16777215</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<!-- included end -->
diff --git a/op-mode-definitions/include/vtysh-generic-detail.xml.i b/op-mode-definitions/include/vtysh-generic-detail.xml.i
new file mode 100644
index 000000000..d469f70c7
--- /dev/null
+++ b/op-mode-definitions/include/vtysh-generic-detail.xml.i
@@ -0,0 +1,8 @@
+<!-- included start from vtysh-generic-detail.xml.i -->
+<leafNode name="detail">
+ <properties>
+ <help>Detailed information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<!-- included end -->
diff --git a/op-mode-definitions/ipoe-server.xml.in b/op-mode-definitions/ipoe-server.xml.in
index 18178f0b0..89cefa08d 100644
--- a/op-mode-definitions/ipoe-server.xml.in
+++ b/op-mode-definitions/ipoe-server.xml.in
@@ -4,17 +4,17 @@
<children>
<node name="ipoe-server">
<properties>
- <help>Clear ipoe-server sessions or process</help>
+ <help>Clear IPoE server sessions or process</help>
</properties>
<children>
<node name="session">
<properties>
- <help>Clear ipoe-server session</help>
+ <help>Clear IPoE server session</help>
</properties>
<children>
<tagNode name="username">
<properties>
- <help>Clear ipoe-server session by username</help>
+ <help>Clear IPoE server session by username</help>
<completionHelp>
<script>${vyos_completion_dir}/list_ipoe.py --selector="username"</script>
</completionHelp>
@@ -23,7 +23,7 @@
</tagNode>
<tagNode name="sid">
<properties>
- <help>Clear ipoe-server session by Session ID</help>
+ <help>Clear IPoE server session by Session ID</help>
<completionHelp>
<script>${vyos_completion_dir}/list_ipoe.py --selector="sid"</script>
</completionHelp>
@@ -32,7 +32,7 @@
</tagNode>
<tagNode name="interface">
<properties>
- <help>Clear ipoe-server session by interface</help>
+ <help>Clear IPoE server session by interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_ipoe.py --selector="ifname"</script>
</completionHelp>
@@ -49,7 +49,7 @@
<children>
<node name="ipoe-server">
<properties>
- <help>show ipoe-server status</help>
+ <help>Show IPoE server status</help>
</properties>
<children>
<leafNode name="sessions">
diff --git a/op-mode-definitions/nat.xml.in b/op-mode-definitions/nat.xml.in
index 4b09816f9..084e2e7e3 100644
--- a/op-mode-definitions/nat.xml.in
+++ b/op-mode-definitions/nat.xml.in
@@ -4,19 +4,19 @@
<children>
<node name="nat">
<properties>
- <help>Show Network Address Translation (NAT) information</help>
+ <help>Show IPv4 to IPv4 Network Address Translation (NAT) information</help>
</properties>
<children>
<node name="source">
<properties>
- <help>Show source Network Address Translation (NAT) information</help>
+ <help>Show source IPv4 to IPv4 Network Address Translation (NAT) information</help>
</properties>
<children>
<node name="rules">
<properties>
<help>Show configured source NAT rules</help>
</properties>
- <command>echo To be migrated to Python - Phabricator T2459</command>
+ <command>${vyos_op_scripts_dir}/show_nat_rules.py --source</command>
</node>
<node name="statistics">
<properties>
@@ -51,14 +51,14 @@
</node>
<node name="destination">
<properties>
- <help>Show destination Network Address Translation (NAT) information</help>
+ <help>Show destination IPv4 to IPv4 Network Address Translation (NAT) information</help>
</properties>
<children>
<node name="rules">
<properties>
<help>Show configured destination NAT rules</help>
</properties>
- <command>echo To be migrated to Python - Phabricator T2459</command>
+ <command>${vyos_op_scripts_dir}/show_nat_rules.py --destination</command>
</node>
<node name="statistics">
<properties>
diff --git a/op-mode-definitions/nat66.xml.in b/op-mode-definitions/nat66.xml.in
new file mode 100644
index 000000000..1ec46eb11
--- /dev/null
+++ b/op-mode-definitions/nat66.xml.in
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interfaceDefinition>
+ <node name="show">
+ <children>
+ <node name="nat66">
+ <properties>
+ <help>Show IPv6 to IPv6 Network Address Translation (NAT66) information</help>
+ </properties>
+ <children>
+ <node name="source">
+ <properties>
+ <help>Show source IPv6 to IPv6 Network Address Translation (NAT66) information</help>
+ </properties>
+ <children>
+ <node name="rules">
+ <properties>
+ <help>Show configured source NAT66 rules</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_rules.py --source</command>
+ </node>
+ <node name="statistics">
+ <properties>
+ <help>Show statistics for configured source NAT66 rules</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_statistics.py --source</command>
+ </node>
+ <node name="translations">
+ <properties>
+ <help>Show active source NAT66 translations</help>
+ </properties>
+ <children>
+ <tagNode name="address">
+ <properties>
+ <help>Show active source NAT66 translations for an IPv6 address</help>
+ <completionHelp>
+ <list>&lt;h:h:h:h:h:h:h:h&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=source --verbose --ipaddr="$6"</command>
+ </tagNode>
+ <node name="detail">
+ <properties>
+ <help>Show active source NAT66 translations detail</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=source --verbose</command>
+ </node>
+ </children>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=source</command>
+ </node>
+ </children>
+ </node>
+ <node name="destination">
+ <properties>
+ <help>Show destination IPv6 to IPv6 Network Address Translation (NAT66) information</help>
+ </properties>
+ <children>
+ <node name="rules">
+ <properties>
+ <help>Show configured destination NAT66 rules</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_rules.py --destination</command>
+ </node>
+ <node name="statistics">
+ <properties>
+ <help>Show statistics for configured destination NAT66 rules</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_statistics.py --destination</command>
+ </node>
+ <node name="translations">
+ <properties>
+ <help>Show active destination NAT66 translations</help>
+ </properties>
+ <children>
+ <tagNode name="address">
+ <properties>
+ <help>Show active NAT66 destination translations for an IPv6 address</help>
+ <completionHelp>
+ <list>&lt;h:h:h:h:h:h:h:h&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=destination --verbose --ipaddr="$6"</command>
+ </tagNode>
+ <node name="detail">
+ <properties>
+ <help>Show active destination NAT66 translations detail</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=destination --verbose</command>
+ </node>
+ </children>
+ <command>${vyos_op_scripts_dir}/show_nat66_translations.py --type=destination</command>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/openconnect.xml.in b/op-mode-definitions/openconnect.xml.in
index 9b82b114e..36f23239e 100644
--- a/op-mode-definitions/openconnect.xml.in
+++ b/op-mode-definitions/openconnect.xml.in
@@ -4,12 +4,12 @@
<children>
<node name="openconnect-server">
<properties>
- <help>show openconnect-server information</help>
+ <help>Show OpenConnect server information</help>
</properties>
<children>
<leafNode name="sessions">
<properties>
- <help>Show active openconnect server sessions</help>
+ <help>Show active OpenConnect server sessions</help>
</properties>
<command>${vyos_op_scripts_dir}/openconnect-control.py --action="show_sessions"</command>
</leafNode>
diff --git a/op-mode-definitions/pppoe-server.xml.in b/op-mode-definitions/pppoe-server.xml.in
index 6d89b3e77..6efdc5a48 100644
--- a/op-mode-definitions/pppoe-server.xml.in
+++ b/op-mode-definitions/pppoe-server.xml.in
@@ -4,7 +4,7 @@
<children>
<node name="pppoe-server">
<properties>
- <help>Show pppoe-server status</help>
+ <help>Show PPPoE server status</help>
</properties>
<children>
<leafNode name="sessions">
@@ -21,7 +21,7 @@
</leafNode>
<leafNode name="interfaces">
<properties>
- <help>Show interfaces where pppoe-server listens on</help>
+ <help>Show interfaces where PPPoE server listens on</help>
</properties>
<command>${vyos_op_scripts_dir}/ppp-server-ctrl.py --proto="pppoe" --action="pppoe interface show"</command>
</leafNode>
@@ -51,13 +51,13 @@
<children>
<leafNode name="all">
<properties>
- <help>Terminate all pppoe-server users</help>
+ <help>Terminate all PPPoE server users</help>
</properties>
<command>${vyos_op_scripts_dir}/ppp-server-ctrl.py --proto="pppoe" --action="terminate all"</command>
</leafNode>
<tagNode name="interface">
<properties>
- <help>Terminate a ppp interface</help>
+ <help>Terminate a PPP interface</help>
</properties>
<command>${vyos_op_scripts_dir}/ppp-server-ctrl.py --proto="pppoe" --action="terminate if $4"</command>
</tagNode>
@@ -85,7 +85,7 @@
<children>
<leafNode name="enable">
<properties>
- <help>Deny new connections and stop to serve pppoe after disconnect last session</help>
+ <help>Deny new connections and stop serving PPPoE after disconnecting the last session</help>
</properties>
<command>${vyos_op_scripts_dir}/ppp-server-ctrl.py --proto="pppoe" --action="shutdown soft"</command>
</leafNode>
diff --git a/op-mode-definitions/show-bgp.xml.in b/op-mode-definitions/show-bgp.xml.in
new file mode 100644
index 000000000..0d0a88dfb
--- /dev/null
+++ b/op-mode-definitions/show-bgp.xml.in
@@ -0,0 +1,257 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="show">
+ <children>
+ <node name="bgp">
+ <properties>
+ <help>BGP information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/bgp-afi-ipv4-ipv6-common.xml.i>
+ <tagNode name="ipv4">
+ <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="ipv4">
+ <properties>
+ <help>IPv4 Address Family</help>
+ </properties>
+ <children>
+ #include <include/bgp-afi-common.xml.i>
+ #include <include/bgp-afi-ipv4-ipv6-common.xml.i>
+ </children>
+ </node>
+ <tagNode name="ipv6">
+ <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="ipv6">
+ <properties>
+ <help>IPv6 Address Family</help>
+ </properties>
+ <children>
+ #include <include/bgp-afi-common.xml.i>
+ #include <include/bgp-afi-ipv4-ipv6-common.xml.i>
+ </children>
+ </node>
+ <node name="l2vpn">
+ <properties>
+ <help>Layer 2 Virtual Private Network</help>
+ </properties>
+ <children>
+ <tagNode name="evpn">
+ <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>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </tagNode>
+ <node name="evpn">
+ <properties>
+ <help>Ethernet Virtual Private Network</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/bgp-afi-common.xml.i>
+ <node name="all">
+ <properties>
+ <help>Display information about all EVPN NLRIs</help>
+ </properties>
+ <children>
+ <leafNode name="overlay">
+ <properties>
+ <help>Display BGP Overlay Information for prefixes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="tags">
+ <properties>
+ <help>Display BGP tags for prefixes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ <node name="es">
+ <properties>
+ <help>Ethernet Segment</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ </children>
+ </node>
+ <node name="es-evi">
+ <properties>
+ <help>Ethernet Segment per EVI</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ #include <include/vni-tagnode.xml.i>
+ </children>
+ </node>
+ <leafNode name="import-rt">
+ <properties>
+ <help>Show import route target</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <tagNode name="neighbors">
+ <properties>
+ <help>Show detailed BGP neighbor information</help>
+ <completionHelp>
+ <script>vtysh -c 'show bgp summary' | awk '{print $1'} | grep -e '^[0-9a-f]'</script>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ <leafNode name="advertised-routes">
+ <properties>
+ <help>Show routes advertised to a BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="routes">
+ <properties>
+ <help>Show routes learned from BGP neighbor</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </tagNode>
+ <tagNode name="rd">
+ <properties>
+ <help>Show detailed BGP neighbor information</help>
+ <completionHelp>
+ <list>ASN:NN IPADDRESS:NN</list>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ <leafNode name="overlay">
+ <properties>
+ <help>Display BGP Overlay Information for prefixes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="tags">
+ <properties>
+ <help>Display BGP tags for prefixes</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </tagNode>
+ <node name="route">
+ <properties>
+ <help>EVPN route information</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/vtysh-generic-detail.xml.i>
+ <node name="type">
+ <properties>
+ <help>Specify Route type</help>
+ </properties>
+ <children>
+ <leafNode name="1">
+ <properties>
+ <help>EAD (Type-1) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="2">
+ <properties>
+ <help>MAC-IP (Type-2) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="3">
+ <properties>
+ <help>Multicast (Type-3) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="4">
+ <properties>
+ <help>Ethernet Segment (Type-4) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="5">
+ <properties>
+ <help>Prefix (Type-5) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="ead">
+ <properties>
+ <help>EAD (Type-1) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="es">
+ <properties>
+ <help>Ethernet Segment (Type-4) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="macip">
+ <properties>
+ <help>MAC-IP (Type-2) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="multicast">
+ <properties>
+ <help>Multicast (Type-3) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ <leafNode name="prefix">
+ <properties>
+ <help>Prefix (Type-5) route</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ #include <include/vni-tagnode-all.xml.i>
+ </children>
+ </node>
+ #include <include/vni-tagnode.xml.i>
+ <leafNode name="vni">
+ <properties>
+ <help>VXLAN network identifier (VNI)</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/show-evpn.xml.in b/op-mode-definitions/show-evpn.xml.in
new file mode 100644
index 000000000..0bdb41e7a
--- /dev/null
+++ b/op-mode-definitions/show-evpn.xml.in
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="show">
+ <children>
+ <node name="evpn">
+ <properties>
+ <help>Show Ethernet VPN (EVPN) information</help>
+ </properties>
+ <children>
+ <node name="arp-cache">
+ <properties>
+ <help>ARP and ND cache</help>
+ </properties>
+ <children>
+ #include <include/vni-tagnode-all.xml.i>
+ </children>
+ </node>
+ <node name="mac">
+ <properties>
+ <help>MAC addresses</help>
+ </properties>
+ <children>
+ #include <include/vni-tagnode-all.xml.i>
+ </children>
+ </node>
+ <node name="next-hops">
+ <properties>
+ <help>Remote VTEPs</help>
+ </properties>
+ <children>
+ #include <include/vni-tagnode-all.xml.i>
+ </children>
+ </node>
+ <node name="rmac">
+ <properties>
+ <help>RMAC</help>
+ </properties>
+ <children>
+ #include <include/vni-tagnode-all.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/op-mode-definitions/show-ip-bgp.xml.in b/op-mode-definitions/show-ip-bgp.xml.in
index 311f9e6ae..690de0a1d 100644
--- a/op-mode-definitions/show-ip-bgp.xml.in
+++ b/op-mode-definitions/show-ip-bgp.xml.in
@@ -22,59 +22,21 @@
</properties>
<command>vtysh -c "show ip bgp cidr-only"</command>
</leafNode>
- <node name="community">
- <properties>
- <help>Show BGP routes matching the communities</help>
- </properties>
- <command>vtysh -c "show ip bgp community"</command>
- </node>
- <tagNode name="community">
- <properties>
- <help>Display routes matching the specified communities</help>
- <completionHelp>
- <list>&lt;AA:NN&gt; local-AS no-advertise no-export</list>
- </completionHelp>
- </properties>
- <command>vtysh -c "show ip bgp community $5"</command>
- </tagNode>
<leafNode name="community-info">
<properties>
<help>List all bgp community information</help>
</properties>
<command>vtysh -c "show ip bgp community-info"</command>
</leafNode>
- <tagNode name="community-list">
- <properties>
- <help>Show BGP routes matching specified community list</help>
- </properties>
- <command>vtysh -c "show ip bgp community-list $5"</command>
- <children>
- <leafNode name="exact-match">
- <properties>
- <help>Show BGP routes exactly matching specified community list</help>
- </properties>
- <command>vtysh -c "show ip bgp community-list $5 exact-match"</command>
- </leafNode>
- </children>
- </tagNode>
- <leafNode name="dampened-paths">
- <properties>
- <help>Show dampened BGP paths</help>
- </properties>
- <command>vtysh -c "show ip bgp dampening dampened-paths"</command>
- </leafNode>
- <tagNode name="filter-list">
+ #include <include/bgp-afi-common.xml.i>
+ #include <include/bgp-afi-ipv4-ipv6-common.xml.i>
+ <tagNode name="prefix-list">
<properties>
- <help>Show BGP information for specified word</help>
+ <completionHelp>
+ <path>policy prefix-list</path>
+ </completionHelp>
</properties>
- <command>vtysh -c "show ip bgp filter-list $5"</command>
</tagNode>
- <leafNode name="flap-statistics">
- <properties>
- <help>Show flap statistics of routes</help>
- </properties>
- <command>vtysh -c "show ip bgp dampening flap-statistics"</command>
- </leafNode>
<node name="ipv4">
<properties>
<help>Show BGP IPv4 information</help>
@@ -120,12 +82,6 @@
</leafNode>
</children>
</tagNode>
- <tagNode name="filter-list">
- <properties>
- <help>Show BGP information for specified word</help>
- </properties>
- <command>vtysh -c "show ip bgp filter-list $5"</command>
- </tagNode>
<tagNode name="neighbors">
<properties>
<help>Show detailed BGP IPv4 unicast neighbor information</help>
@@ -204,198 +160,26 @@
</tagNode>
</children>
</node>
- <node name="l2vpn">
- <properties>
- <help>Layer 2 Virtual Private Network</help>
- </properties>
- <children>
- <node name="evpn">
- <properties>
- <help>Ethernet Virtual Private Network</help>
- </properties>
- <children>
- <node name="all">
- <properties>
- <help>Display information about all EVPN NLRIs</help>
- </properties>
- <children>
- <leafNode name="overlay">
- <properties>
- <help>Display BGP Overlay Information for prefixes</help>
- </properties>
- <command>vtysh -c "show ip bgp l2vpn evpn all overlay"</command>
- </leafNode>
- <leafNode name="tags">
- <properties>
- <help>Display BGP tags for prefixes</help>
- </properties>
- <command>vtysh -c "show ip bgp l2vpn evpn all tags"</command>
- </leafNode>
- </children>
- </node>
- <tagNode name="neighbors">
- <properties>
- <help>Show detailed BGP IPv4 unicast neighbor information</help>
- <completionHelp>
- <script>vtysh -c "show ip bgp summary" | awk '{print $1}' | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"</script>
- </completionHelp>
- </properties>
- <children>
- <leafNode name="advertised-routes">
- <properties>
- <help>Show routes advertised to a BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp l2vpn evpn neighbor $7 advertised-routes"</command>
- </leafNode>
- <leafNode name="routes">
- <properties>
- <help>Show routes learned from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp l2vpn evpn neighbor $7 routes"</command>
- </leafNode>
- </children>
- </tagNode>
- <leafNode name="update-groups">
- <properties>
- <help>Detailed info about dynamic update groups</help>
- </properties>
- <command>vtysh -c "show ip bgp l2vpn evpn update-groups"</command>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
- <node name="large-community">
- <properties>
- <help>Show BGP routes matching the specified large-communities</help>
- </properties>
- <command>vtysh -c "show ip bgp large-community"</command>
- </node>
<leafNode name="large-community-info">
<properties>
<help>Show BGP large-community information</help>
</properties>
<command>vtysh -c "show ip bgp large-community-info"</command>
</leafNode>
- <tagNode name="large-community-list">
- <properties>
- <help>Show BGP routes matching the specified large-community list</help>
- </properties>
- <command>vtysh -c "show ip bgp large-community-list $5"</command>
- </tagNode>
<leafNode name="memory">
<properties>
<help>Show BGP memory usage</help>
</properties>
<command>vtysh -c "show ip bgp memory"</command>
</leafNode>
- <tagNode name="neighbors">
- <properties>
- <help>Show detailed BGP IPv4 unicast neighbor information</help>
- <completionHelp>
- <script>vtysh -c "show ip bgp summary" | awk '{print $1}' | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"</script>
- </completionHelp>
- </properties>
- <command>vtysh -c "show ip bgp neighbors $5"</command>
- <children>
- <leafNode name="advertised-routes">
- <properties>
- <help>Show routes advertised to a BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 advertised-routes"</command>
- </leafNode>
- <leafNode name="dampened-routes">
- <properties>
- <help>Show dampened routes received from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 dampened-routes"</command>
- </leafNode>
- <leafNode name="flap-statistics">
- <properties>
- <help>Show flap statistics of the routes learned from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 flap-statistics"</command>
- </leafNode>
- <leafNode name="prefix-counts">
- <properties>
- <help>Show detailed prefix count information for BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 prefix-counts"</command>
- </leafNode>
- <node name="received">
- <properties>
- <help>Show information received from BGP neighbor</help>
- </properties>
- <children>
- <leafNode name="prefix-filter">
- <properties>
- <help>Show prefixlist filter</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 received prefix-filter"</command>
- </leafNode>
- </children>
- </node>
- <leafNode name="received-routes">
- <properties>
- <help>Show received routes from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 received-routes"</command>
- </leafNode>
- <leafNode name="routes">
- <properties>
- <help>Show routes learned from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show ip bgp neighbor $5 routes"</command>
- </leafNode>
- </children>
- </tagNode>
<leafNode name="paths">
<properties>
<help>Show BGP path information</help>
</properties>
<command>vtysh -c "show ip bgp paths"</command>
</leafNode>
- <tagNode name="prefix-list">
- <properties>
- <help>Show BGP routes matching the specified prefix list</help>
- </properties>
- <command>vtysh -c "show ip bgp prefix-list $5"</command>
- </tagNode>
- <tagNode name="regexp">
- <properties>
- <help>Show BGP routes matching the specified AS path regular expression</help>
- </properties>
- <command>vtysh -c "show ip bgp regexp $5"</command>
- </tagNode>
- <tagNode name="route-map">
- <properties>
- <help>Show BGP routes matching the specified route map</help>
- </properties>
- <command>vtysh -c "show ip bgp route-map $5"</command>
- </tagNode>
- <leafNode name="statistics">
- <properties>
- <help>Show summary of BGP information</help>
- </properties>
- <command>vtysh -c "show ip bgp statistics"</command>
- </leafNode>
- <leafNode name="summary">
- <properties>
- <help>Show summary of BGP information</help>
- </properties>
- <command>vtysh -c "show ip bgp summary"</command>
- </leafNode>
</children>
</node>
- <tagNode name="bgp">
- <properties>
- <help>Show BGP information for specified IP address or prefix</help>
- <completionHelp>
- <list>&lt;x.x.x.x&gt; &lt;x.x.x.x/x&gt;</list>
- </completionHelp>
- </properties>
- <command>vtysh -c "show ip bgp $4"</command>
- </tagNode>
</children>
</node>
</children>
diff --git a/op-mode-definitions/show-ipv6-bgp.xml.in b/op-mode-definitions/show-ipv6-bgp.xml.in
deleted file mode 100644
index aad61b97a..000000000
--- a/op-mode-definitions/show-ipv6-bgp.xml.in
+++ /dev/null
@@ -1,203 +0,0 @@
-<?xml version="1.0"?>
-<interfaceDefinition>
- <node name="show">
- <children>
- <node name="ipv6">
- <properties>
- <help>Show IPv6 routing information</help>
- </properties>
- <children>
- <node name="bgp">
- <properties>
- <help>Show Border Gateway Protocol (BGP) information</help>
- </properties>
- <command>vtysh -c "show bgp ipv6"</command>
- <children>
- <leafNode name="summary">
- <properties>
- <help>Show summary of BGP neighbor status</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 summary"</command>
- </leafNode>
- <tagNode name="regexp">
- <properties>
- <help>Show routes matching AS path regular expression</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 regexp $5"</command>
- </tagNode>
- <tagNode name="prefix-list">
- <properties>
- <help>Show routes matching the IPv6 prefix-list name</help>
- <completionHelp>
- <path>policy prefix-list6</path>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 prefix-list $5"</command>
- </tagNode>
- <tagNode name="neighbors">
- <properties>
- <help>Show detailed information on TCP and BGP neighbor connections for given address</help>
- <completionHelp>
- <script>vtysh -c "show bgp ipv6 summary" | awk '{print $1}' | grep -oE "\b([0-9a-f]{1,4}\:{0,2}){0,20}\b"</script>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5"</command>
- <children>
- <leafNode name="advertised-routes">
- <properties>
- <help>Show routes advertised to a BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 advertised-routes"</command>
- </leafNode>
- <leafNode name="filtered-routes">
- <properties>
- <help>Show routes filtered from a BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 filtered-routes"</command>
- </leafNode>
- <leafNode name="dampened-routes">
- <properties>
- <help>Show dampened routes received from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 dampened-routes"</command>
- </leafNode>
- <leafNode name="flap-statistics">
- <properties>
- <help>Show flap statistics of the routes learned from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 flap-statistics"</command>
- </leafNode>
- <leafNode name="prefix-counts">
- <properties>
- <help>Show detailed prefix count information for BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 prefix-counts"</command>
- </leafNode>
- <node name="received">
- <properties>
- <help>Show information received from BGP neighbor</help>
- </properties>
- <children>
- <leafNode name="prefix-filter">
- <properties>
- <help>Show prefixlist filter</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 received prefix-filter"</command>
- </leafNode>
- </children>
- </node>
- <leafNode name="received-routes">
- <properties>
- <help>Show received routes from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 received-routes"</command>
- </leafNode>
- <leafNode name="routes">
- <properties>
- <help>Show routes learned from BGP neighbor</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 neighbor $5 routes"</command>
- </leafNode>
- </children>
- </tagNode>
- <tagNode name="large-community">
- <properties>
- <help>Show routes matching the large-community-list number or name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 large-community-list $5"</command>
- <children>
- <node name="exact-match">
- <properties>
- <help>Show routes matching the large-community-list number or name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 large-community-list $5 exact-match"</command>
- </node>
- </children>
- </tagNode>
- <tagNode name="large-community-list">
- <properties>
- <help>Show routes matching the large-community-list number or name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 large-community-list $5"</command>
- <children>
- <node name="exact-match">
- <properties>
- <help>Show routes matching the large-community-list number or name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 large-community-list $5 exact-match"</command>
- </node>
- </children>
- </tagNode>
- <tagNode name="filter-list">
- <properties>
- <help>Show routes conforming to regular expression access list name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 filter-list $5"</command>
- </tagNode>
- <tagNode name="community">
- <properties>
- <help>Show BGP information for specified community number</help>
- <completionHelp>
- <list>&lt;AA:NN&gt; local-AS no-advertise no-export</list>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 community $5"</command>
- <children>
- <node name="exact-match">
- <properties>
- <help>Show routes from community that exactly matches the community number</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 community $5 exact-match"</command>
- </node>
- </children>
- </tagNode>
- <tagNode name="community-list">
- <properties>
- <help>Show routes matching the community-list number or name</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 community-list $5"</command>
- <children>
- <node name="exact-match">
- <properties>
- <help>Show routes exactly matching the community-list name or number</help>
- </properties>
- <command>vtysh -c "show bgp ipv6 community-list $5 exact-match"</command>
- </node>
- </children>
- </tagNode>
- <tagNode name="route-map">
- <properties>
- <help>Show BGP routes matching the specified route map</help>
- <completionHelp>
- <path>policy route-map</path>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 route-map $5"</command>
- </tagNode>
- </children>
- </node>
- <tagNode name="bgp">
- <properties>
- <help>Show BGP information for specified IP address or prefix</help>
- <completionHelp>
- <list>&lt;h:h:h:h:h:h:h:h&gt; &lt;h:h:h:h:h:h:h:h/x&gt;</list>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 $4"</command>
- <children>
- <node name="longer-prefixes">
- <properties>
- <help>Show route and more specific routes</help>
- <completionHelp>
- <list>&lt;h:h:h:h:h:h:h:h&gt; &lt;h:h:h:h:h:h:h:h/x&gt;</list>
- </completionHelp>
- </properties>
- <command>vtysh -c "show bgp ipv6 $4 longer-prefixes"</command>
- </node>
- </children>
- </tagNode>
- </children>
- </node>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/op-mode-definitions/wireguard.xml.in b/op-mode-definitions/wireguard.xml.in
index 69ba8043d..4aee4b1ac 100644
--- a/op-mode-definitions/wireguard.xml.in
+++ b/op-mode-definitions/wireguard.xml.in
@@ -1,28 +1,28 @@
<?xml version="1.0"?>
-<!-- wireguard key management -->
+<!-- Wireguard key management -->
<interfaceDefinition>
<node name="generate">
<children>
<node name="wireguard">
<properties>
- <help>wireguard key generation utility</help>
+ <help>Generate Wireguard keys</help>
</properties>
<children>
<leafNode name="default-keypair">
<properties>
- <help>generates the wireguard default-keypair</help>
+ <help>Generate the default Wireguard keypair</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/wireguard.py --genkey</command>
</leafNode>
<leafNode name="preshared-key">
<properties>
- <help>generate a wireguard preshared key</help>
+ <help>Generate a Wireguard preshared key</help>
</properties>
<command>${vyos_op_scripts_dir}/wireguard.py --genpsk</command>
</leafNode>
<tagNode name="named-keypairs">
<properties>
- <help>Generates named wireguard keypairs</help>
+ <help>Generate specified Wireguard keypairs</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/wireguard.py --genkey --location "$4"</command>
</tagNode>
@@ -34,17 +34,17 @@
<children>
<node name="wireguard">
<properties>
- <help>Show wireguard properties</help>
+ <help>Show Wireguard properties</help>
</properties>
<children>
<node name="keypairs">
<properties>
- <help>Shows named wireguard keys</help>
+ <help>Show Wireguard keys</help>
</properties>
<children>
<tagNode name="pubkey">
<properties>
- <help>Show wireguard private named key</help>
+ <help>Show specified Wireguard public key</help>
<completionHelp>
<script>${vyos_op_scripts_dir}/wireguard.py --listkdir</script>
</completionHelp>
@@ -53,7 +53,7 @@
</tagNode>
<tagNode name="privkey">
<properties>
- <help>Show wireguard public named key</help>
+ <help>Show specified Wireguard private key</help>
<completionHelp>
<script>${vyos_op_scripts_dir}/wireguard.py --listkdir</script>
</completionHelp>
@@ -68,7 +68,7 @@
<children>
<tagNode name="wireguard">
<properties>
- <help>show wireguard interface information</help>
+ <help>Show Wireguard interface information</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces.py --type wireguard</script>
</completionHelp>
@@ -77,19 +77,19 @@
<children>
<leafNode name="allowed-ips">
<properties>
- <help>show all allowed-ips for the specified interface</help>
+ <help>Show all IP addresses allowed for the specified interface</help>
</properties>
<command>sudo wg show "$4" allowed-ips</command>
</leafNode>
<leafNode name="endpoints">
<properties>
- <help>show all endpoints for the specified interface</help>
+ <help>Show all endpoints for the specified interface</help>
</properties>
<command>sudo wg show "$4" endpoints</command>
</leafNode>
<leafNode name="peers">
<properties>
- <help>show all peer IDs for the specified interface</help>
+ <help>Show all peer IDs for the specified interface</help>
</properties>
<command>sudo wg show "$4" peers</command>
</leafNode>
@@ -98,13 +98,13 @@
</tagNode>
<node name="wireguard">
<properties>
- <help>Show wireguard interface information</help>
+ <help>Show Wireguard interface information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=wireguard --action=show-brief</command>
<children>
<leafNode name="detail">
<properties>
- <help>Show detailed wireguard interface information</help>
+ <help>Show detailed Wireguard interface information</help>
</properties>
<command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=wireguard --action=show</command>
</leafNode>
@@ -118,12 +118,12 @@
<children>
<node name="wireguard">
<properties>
- <help>Delete wireguard properties</help>
+ <help>Delete Wireguard properties</help>
</properties>
<children>
<tagNode name="keypair">
<properties>
- <help>Delete a wireguard keypair</help>
+ <help>Delete a Wireguard keypair</help>
<completionHelp>
<script>${vyos_op_scripts_dir}/wireguard.py --listkdir</script>
</completionHelp>
diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py
index 82b9355a3..670e6c7fc 100644
--- a/python/vyos/configsession.py
+++ b/python/vyos/configsession.py
@@ -129,9 +129,9 @@ class ConfigSession(object):
def __run_command(self, cmd_list):
p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=self.__session_env)
+ (stdout_data, stderr_data) = p.communicate()
+ output = stdout_data.decode()
result = p.wait()
- output = p.stdout.read().decode()
- p.communicate()
if result != 0:
raise ConfigSessionError(output)
return output
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index 5a4d14c68..7cf2cb8f9 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -95,41 +95,42 @@ def verify_tunnel(config):
"""
from vyos.template import is_ipv4
from vyos.template import is_ipv6
-
+
if 'encapsulation' not in config:
raise ConfigError('Must configure the tunnel encapsulation for '\
'{ifname}!'.format(**config))
-
- if 'local_ip' not in config and 'dhcp_interface' not in config:
- raise ConfigError('local-ip is mandatory for tunnel')
- if 'remote_ip' not in config and config['encapsulation'] != 'gre':
- raise ConfigError('remote-ip is mandatory for tunnel')
+ if 'source_address' not in config and 'dhcp_interface' not in config:
+ raise ConfigError('source-address is mandatory for tunnel')
+
+ if 'remote' not in config and config['encapsulation'] != 'gre':
+ raise ConfigError('remote ip address is mandatory for tunnel')
- if {'local_ip', 'dhcp_interface'} <= set(config):
- raise ConfigError('Can not use both local-ip and dhcp-interface')
+ if {'source_address', 'dhcp_interface'} <= set(config):
+ raise ConfigError('Can not use both source-address and dhcp-interface')
- if config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre', 'ip6erspan']:
+ if config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre', 'ip6gretap', 'ip6erspan']:
error_ipv6 = 'Encapsulation mode requires IPv6'
- if 'local_ip' in config and not is_ipv6(config['local_ip']):
- raise ConfigError(f'{error_ipv6} local-ip')
+ if 'source_address' in config and not is_ipv6(config['source_address']):
+ raise ConfigError(f'{error_ipv6} source-address')
- if 'remote_ip' in config and not is_ipv6(config['remote_ip']):
- raise ConfigError(f'{error_ipv6} remote-ip')
+ if 'remote' in config and not is_ipv6(config['remote']):
+ raise ConfigError(f'{error_ipv6} remote')
else:
error_ipv4 = 'Encapsulation mode requires IPv4'
- if 'local_ip' in config and not is_ipv4(config['local_ip']):
- raise ConfigError(f'{error_ipv4} local-ip')
+ if 'source_address' in config and not is_ipv4(config['source_address']):
+ raise ConfigError(f'{error_ipv4} source-address')
- if 'remote_ip' in config and not is_ipv4(config['remote_ip']):
- raise ConfigError(f'{error_ipv4} remote-ip')
+ if 'remote' in config and not is_ipv4(config['remote']):
+ raise ConfigError(f'{error_ipv4} remote address')
- if config['encapsulation'] in ['sit', 'gre-bridge']:
+ if config['encapsulation'] in ['sit', 'gretap', 'ip6gretap']:
if 'source_interface' in config:
- raise ConfigError('Option source-interface can not be used with ' \
- 'encapsulation "sit" or "gre-bridge"')
+ encapsulation = config['encapsulation']
+ raise ConfigError(f'Option source-interface can not be used with ' \
+ f'encapsulation "{encapsulation}"!')
elif config['encapsulation'] == 'gre':
- if 'local_ip' in config and is_ipv6(config['local_ip']):
+ if 'source_address' in config and is_ipv6(config['source_address']):
raise ConfigError('Can not use local IPv6 address is for mGRE tunnels')
def verify_eapol(config):
diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py
new file mode 100644
index 000000000..136feae8d
--- /dev/null
+++ b/python/vyos/ethtool.py
@@ -0,0 +1,101 @@
+# Copyright 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
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+from vyos.util import popen
+
+class Ethtool:
+ """
+ Class is used to retrive and cache information about an ethernet adapter
+ """
+
+ # dictionary containing driver featurs, it will be populated on demand and
+ # the content will look like:
+ # {
+ # 'tls-hw-tx-offload': {'fixed': True, 'on': False},
+ # 'tx-checksum-fcoe-crc': {'fixed': True, 'on': False},
+ # 'tx-checksum-ip-generic': {'fixed': False, 'on': True},
+ # 'tx-checksum-ipv4': {'fixed': True, 'on': False},
+ # 'tx-checksum-ipv6': {'fixed': True, 'on': False},
+ # 'tx-checksum-sctp': {'fixed': True, 'on': False},
+ # 'tx-checksumming': {'fixed': False, 'on': True},
+ # 'tx-esp-segmentation': {'fixed': True, 'on': False},
+ # }
+ features = { }
+ ring_buffers = { }
+
+ def __init__(self, ifname):
+ # Now populate features dictionaty
+ out, err = popen(f'ethtool -k {ifname}')
+ # skip the first line, it only says: "Features for eth0":
+ for line in out.splitlines()[1:]:
+ if ":" in line:
+ key, value = [s.strip() for s in line.strip().split(":", 1)]
+ fixed = "fixed" in value
+ if fixed:
+ value = value.split()[0].strip()
+ self.features[key.strip()] = {
+ "on": value == "on",
+ "fixed": fixed
+ }
+
+ out, err = popen(f'ethtool -g {ifname}')
+ # We are only interested in line 2-5 which contains the device maximum
+ # ringbuffers
+ for line in out.splitlines()[2:6]:
+ if ':' in line:
+ key, value = [s.strip() for s in line.strip().split(":", 1)]
+ key = key.lower().replace(' ', '_')
+ self.ring_buffers[key] = int(value)
+
+
+ def is_fixed_lro(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('large-receive-offload', True).get('fixed', True)
+
+ def is_fixed_gro(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('generic-receive-offload', True).get('fixed', True)
+
+ def is_fixed_gso(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('generic-segmentation-offload', True).get('fixed', True)
+
+ def is_fixed_sg(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('scatter-gather', True).get('fixed', True)
+
+ def is_fixed_tso(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('tcp-segmentation-offload', True).get('fixed', True)
+
+ def is_fixed_ufo(self):
+ # in case of a missing configuration, rather return "fixed". In Ethtool
+ # terminology "fixed" means the setting can not be changed by the user.
+ return self.features.get('udp-fragmentation-offload', True).get('fixed', True)
+
+ def get_rx_buffer(self):
+ # Configuration of RX ring-buffers is not supported on every device,
+ # thus when it's impossible return None
+ return self.ring_buffers.get('rx', None)
+
+ def get_tx_buffer(self):
+ # Configuration of TX ring-buffers is not supported on every device,
+ # thus when it's impossible return None
+ return self.ring_buffers.get('tx', None)
diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py
index f7b55c9dd..f5dfa8e05 100644
--- a/python/vyos/ifconfig/__init__.py
+++ b/python/vyos/ifconfig/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -31,14 +31,7 @@ from vyos.ifconfig.wireguard import WireGuardIf
from vyos.ifconfig.vtun import VTunIf
from vyos.ifconfig.vti import VTIIf
from vyos.ifconfig.pppoe import PPPoEIf
-from vyos.ifconfig.tunnel import GREIf
-from vyos.ifconfig.tunnel import GRETapIf
-from vyos.ifconfig.tunnel import IP6GREIf
-from vyos.ifconfig.tunnel import IPIPIf
-from vyos.ifconfig.tunnel import IPIP6If
-from vyos.ifconfig.tunnel import IP6IP6If
-from vyos.ifconfig.tunnel import SitIf
-from vyos.ifconfig.tunnel import Sit6RDIf
+from vyos.ifconfig.tunnel import TunnelIf
from vyos.ifconfig.erspan import ERSpanIf
from vyos.ifconfig.erspan import ER6SpanIf
from vyos.ifconfig.wireless import WiFiIf
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py
index 709222b09..bfa3b0025 100644
--- a/python/vyos/ifconfig/bond.py
+++ b/python/vyos/ifconfig/bond.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -31,9 +31,7 @@ class BondIf(Interface):
monitoring may be performed.
"""
- default = {
- 'type': 'bond',
- }
+ iftype = 'bond'
definition = {
**Interface.definition,
** {
@@ -343,9 +341,6 @@ class BondIf(Interface):
if 'shutdown_required' in config:
self.set_admin_state('down')
- # call base class first
- super().update(config)
-
# ARP monitor targets need to be synchronized between sysfs and CLI.
# Unfortunately an address can't be send twice to sysfs as this will
# result in the following exception: OSError: [Errno 22] Invalid argument.
@@ -404,12 +399,5 @@ class BondIf(Interface):
value = config.get('primary')
if value: self.set_primary(value)
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py
index 1bd617a05..600bd3db8 100644
--- a/python/vyos/ifconfig/bridge.py
+++ b/python/vyos/ifconfig/bridge.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -34,10 +34,7 @@ class BridgeIf(Interface):
The Linux bridge code implements a subset of the ANSI/IEEE 802.1d standard.
"""
-
- default = {
- 'type': 'bridge',
- }
+ iftype = 'bridge'
definition = {
**Interface.definition,
**{
@@ -236,11 +233,6 @@ class BridgeIf(Interface):
interface setup code and provide a single point of entry when workin
on any interface. """
- # call base class first
- super().update(config)
-
- ifname = config['ifname']
-
# Set ageing time
value = config.get('aging')
self.set_ageing_time(value)
@@ -280,24 +272,25 @@ class BridgeIf(Interface):
vlan_filter = '1' if 'enable_vlan' in config else '0'
self.set_vlan_filter(vlan_filter)
+ ifname = config['ifname']
if int(vlan_filter):
add_vlan = []
cur_vlan_ids = get_vlan_ids(ifname)
-
+
tmp = dict_search('vif', config)
if tmp:
for vif, vif_config in tmp.items():
add_vlan.append(vif)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {ifname} vid {vlan} self'
self._cmd(cmd)
-
+
for vlan in add_vlan:
cmd = f'bridge vlan add dev {ifname} vid {vlan} self'
self._cmd(cmd)
-
+
# VLAN of bridge parent interface is always 1
# VLAN 1 is the default VLAN for all unlabeled packets
cmd = f'bridge vlan add dev {ifname} vid 1 pvid untagged self'
@@ -337,7 +330,7 @@ class BridgeIf(Interface):
native_vlan_id = None
allowed_vlan_ids= []
cur_vlan_ids = get_vlan_ids(interface)
-
+
if 'native_vlan' in interface_config:
vlan_id = interface_config['native_vlan']
add_vlan.append(vlan_id)
@@ -353,12 +346,12 @@ class BridgeIf(Interface):
else:
add_vlan.append(vlan)
allowed_vlan_ids.append(vlan)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {interface} vid {vlan} master'
self._cmd(cmd)
-
+
for vlan in allowed_vlan_ids:
cmd = f'bridge vlan add dev {interface} vid {vlan} master'
self._cmd(cmd)
@@ -367,12 +360,5 @@ class BridgeIf(Interface):
cmd = f'bridge vlan add dev {interface} vid {native_vlan_id} pvid untagged master'
self._cmd(cmd)
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py
index 43136f361..d41dfef47 100644
--- a/python/vyos/ifconfig/control.py
+++ b/python/vyos/ifconfig/control.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
diff --git a/python/vyos/ifconfig/dummy.py b/python/vyos/ifconfig/dummy.py
index 19ef9d304..d45769931 100644
--- a/python/vyos/ifconfig/dummy.py
+++ b/python/vyos/ifconfig/dummy.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -23,9 +23,7 @@ class DummyIf(Interface):
packets through without actually transmitting them.
"""
- default = {
- 'type': 'dummy',
- }
+ iftype = 'dummy'
definition = {
**Interface.definition,
**{
@@ -33,22 +31,3 @@ class DummyIf(Interface):
'prefixes': ['dum', ],
},
}
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/erspan.py b/python/vyos/ifconfig/erspan.py
index 50230e14a..03b2acdbf 100755
--- a/python/vyos/ifconfig/erspan.py
+++ b/python/vyos/ifconfig/erspan.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -31,12 +31,7 @@ class _ERSpan(Interface):
"""
_ERSpan: private base class for ERSPAN tunnels
"""
- default = {
- **Interface.default,
- **{
- 'type': 'erspan',
- }
- }
+ iftype = 'erspan'
definition = {
**Interface.definition,
**{
@@ -44,29 +39,14 @@ class _ERSpan(Interface):
'prefixes': ['ersp',],
},
}
-
- options = ['local_ip','remote_ip','encapsulation','parameters']
-
+
def __init__(self,ifname,**config):
self.config = deepcopy(config) if config else {}
super().__init__(ifname, **self.config)
-
+
def change_options(self):
pass
-
- def update(self, config):
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- super().update(config)
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
+
def _create(self):
pass
@@ -74,15 +54,15 @@ class ERSpanIf(_ERSpan):
"""
ERSpanIf: private base class for ERSPAN Over GRE and IPv4 tunnels
"""
-
+
def _create(self):
ifname = self.config['ifname']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ source_address = self.config['source_address']
+ remote = self.config['remote']
key = self.config['parameters']['ip']['key']
version = self.config['parameters']['version']
- command = f'ip link add dev {ifname} type erspan local {local_ip} remote {remote_ip} seq key {key} erspan_ver {version}'
-
+ command = f'ip link add dev {ifname} type erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
+
if int(version) == 1:
idx=dict_search('parameters.erspan.idx',self.config)
if idx:
@@ -94,24 +74,24 @@ class ERSpanIf(_ERSpan):
hwid=dict_search('parameters.erspan.hwid',self.config)
if hwid:
command += f' erspan_hwid {hwid}'
-
+
ttl = dict_search('parameters.ip.ttl',self.config)
if ttl:
command += f' ttl {ttl}'
tos = dict_search('parameters.ip.tos',self.config)
if tos:
command += f' tos {tos}'
-
+
self._cmd(command)
-
+
def change_options(self):
ifname = self.config['ifname']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ source_address = self.config['source_address']
+ remote = self.config['remote']
key = self.config['parameters']['ip']['key']
version = self.config['parameters']['version']
- command = f'ip link set dev {ifname} type erspan local {local_ip} remote {remote_ip} seq key {key} erspan_ver {version}'
-
+ command = f'ip link set dev {ifname} type erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
+
if int(version) == 1:
idx=dict_search('parameters.erspan.idx',self.config)
if idx:
@@ -123,29 +103,29 @@ class ERSpanIf(_ERSpan):
hwid=dict_search('parameters.erspan.hwid',self.config)
if hwid:
command += f' erspan_hwid {hwid}'
-
+
ttl = dict_search('parameters.ip.ttl',self.config)
if ttl:
command += f' ttl {ttl}'
tos = dict_search('parameters.ip.tos',self.config)
if tos:
command += f' tos {tos}'
-
+
self._cmd(command)
class ER6SpanIf(_ERSpan):
"""
ER6SpanIf: private base class for ERSPAN Over GRE and IPv6 tunnels
"""
-
+
def _create(self):
ifname = self.config['ifname']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ source_address = self.config['source_address']
+ remote = self.config['remote']
key = self.config['parameters']['ip']['key']
version = self.config['parameters']['version']
- command = f'ip link add dev {ifname} type ip6erspan local {local_ip} remote {remote_ip} seq key {key} erspan_ver {version}'
-
+ command = f'ip link add dev {ifname} type ip6erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
+
if int(version) == 1:
idx=dict_search('parameters.erspan.idx',self.config)
if idx:
@@ -157,24 +137,24 @@ class ER6SpanIf(_ERSpan):
hwid=dict_search('parameters.erspan.hwid',self.config)
if hwid:
command += f' erspan_hwid {hwid}'
-
+
ttl = dict_search('parameters.ip.ttl',self.config)
if ttl:
command += f' ttl {ttl}'
tos = dict_search('parameters.ip.tos',self.config)
if tos:
command += f' tos {tos}'
-
+
self._cmd(command)
-
+
def change_options(self):
ifname = self.config['ifname']
- local_ip = self.config['local_ip']
- remote_ip = self.config['remote_ip']
+ source_address = self.config['source_address']
+ remote = self.config['remote']
key = self.config['parameters']['ip']['key']
version = self.config['parameters']['version']
- command = f'ip link set dev {ifname} type ip6erspan local {local_ip} remote {remote_ip} seq key {key} erspan_ver {version}'
-
+ command = f'ip link set dev {ifname} type ip6erspan local {source_address} remote {remote} seq key {key} erspan_ver {version}'
+
if int(version) == 1:
idx=dict_search('parameters.erspan.idx',self.config)
if idx:
@@ -186,5 +166,5 @@ class ER6SpanIf(_ERSpan):
hwid=dict_search('parameters.erspan.hwid',self.config)
if hwid:
command += f' erspan_hwid {hwid}'
-
+
self._cmd(command)
diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py
index 547b54b84..b89ca5a5c 100644
--- a/python/vyos/ifconfig/ethernet.py
+++ b/python/vyos/ifconfig/ethernet.py
@@ -26,10 +26,7 @@ class EthernetIf(Interface):
"""
Abstraction of a Linux Ethernet Interface
"""
-
- default = {
- 'type': 'ethernet',
- }
+ iftype = 'ethernet'
definition = {
**Interface.definition,
**{
@@ -321,9 +318,6 @@ class EthernetIf(Interface):
interface setup code and provide a single point of entry when workin
on any interface. """
- # call base class first
- super().update(config)
-
# disable ethernet flow control (pause frames)
value = 'off' if 'disable_flow_control' in config else 'on'
self.set_flow_control(value)
@@ -357,12 +351,5 @@ class EthernetIf(Interface):
for b_type in config['ring_buffer']:
self.set_ring_buffer(b_type, config['ring_buffer'][b_type])
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ # call base class first
+ super().update(config)
diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py
index 5c4597be8..7cb3968df 100644
--- a/python/vyos/ifconfig/geneve.py
+++ b/python/vyos/ifconfig/geneve.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -13,7 +13,8 @@
# 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/>.
-from vyos.ifconfig.interface import Interface
+from vyos.ifconfig import Interface
+from vyos.util import dict_search
@Interface.register
class GeneveIf(Interface):
@@ -26,14 +27,7 @@ class GeneveIf(Interface):
https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/#geneve
https://lwn.net/Articles/644938/
"""
-
- default = {
- 'type': 'geneve',
- 'vni': 0,
- 'remote': '',
- }
- options = Interface.options + \
- ['vni', 'remote']
+ iftype = 'geneve'
definition = {
**Interface.definition,
**{
@@ -44,27 +38,27 @@ class GeneveIf(Interface):
}
def _create(self):
- cmd = 'ip link add name {ifname} type geneve id {vni} remote {remote}'.format(**self.config)
- self._cmd(cmd)
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ mapping = {
+ 'parameters.ip.dont_fragment': 'df set',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ }
+
+ cmd = 'ip link add name {ifname} type {type} id {vni} remote {remote}'
+ for vyos_key, iproute2_key in mapping.items():
+ # dict_search will return an empty dict "{}" for valueless nodes like
+ # "parameters.nolearning" - thus we need to test the nodes existence
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+ self._cmd(cmd.format(**self.config))
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/input.py b/python/vyos/ifconfig/input.py
index a6e566d87..db7d2b6b4 100644
--- a/python/vyos/ifconfig/input.py
+++ b/python/vyos/ifconfig/input.py
@@ -17,9 +17,6 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class InputIf(Interface):
- default = {
- 'type': '',
- }
definition = {
**Interface.definition,
**{
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index d9507d816..fe6a3c95e 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -60,7 +60,6 @@ class Interface(Control):
options = ['debug', 'create']
required = []
default = {
- 'type': '',
'debug': True,
'create': True,
}
@@ -232,26 +231,21 @@ class Interface(Control):
>>> from vyos.ifconfig import Interface
>>> i = Interface('eth0')
"""
+ self.config = deepcopy(kargs)
+ self.config['ifname'] = self.ifname = ifname
- self.config = deepcopy(self.default)
- for k in self.options:
- if k in kargs:
- self.config[k] = kargs[k]
-
- # make sure the ifname is the first argument and not from the dict
- self.config['ifname'] = ifname
self._admin_state_down_cnt = 0
# we must have updated config before initialising the Interface
super().__init__(**kargs)
- self.ifname = ifname
if not self.exists(ifname):
- # Any instance of Interface, such as Interface('eth0')
- # can be used safely to access the generic function in this class
- # as 'type' is unset, the class can not be created
- if not self.config['type']:
+ # Any instance of Interface, such as Interface('eth0') can be used
+ # safely to access the generic function in this class as 'type' is
+ # unset, the class can not be created
+ if not self.iftype:
raise Exception(f'interface "{ifname}" not found')
+ self.config['type'] = self.iftype
# Should an Instance of a child class (EthernetIf, DummyIf, ..)
# be required, then create should be set to False to not accidentally create it.
@@ -923,12 +917,12 @@ class Interface(Control):
else:
add_vlan.append(vlan)
allowed_vlan_ids.append(vlan)
-
+
# Remove redundant VLANs from the system
for vlan in list_diff(cur_vlan_ids, add_vlan):
cmd = f'bridge vlan del dev {ifname} vid {vlan} master'
self._cmd(cmd)
-
+
for vlan in allowed_vlan_ids:
cmd = f'bridge vlan add dev {ifname} vid {vlan} master'
self._cmd(cmd)
@@ -951,6 +945,9 @@ class Interface(Control):
pid_file = f'{config_base}_{ifname}.pid'
lease_file = f'{config_base}_{ifname}.leases'
+ # Stop client with old config files to get the right IF_METRIC.
+ self._cmd(f'systemctl stop dhclient@{ifname}.service')
+
if enable and 'disable' not in self._config:
if dict_search('dhcp_options.host_name', self._config) == None:
# read configured system hostname.
@@ -969,10 +966,8 @@ class Interface(Control):
# 'up' check is mandatory b/c even if the interface is A/D, as soon as
# the DHCP client is started the interface will be placed in u/u state.
# This is not what we intended to do when disabling an interface.
- return self._cmd(f'systemctl restart dhclient@{ifname}.service')
+ return self._cmd(f'systemctl start dhclient@{ifname}.service')
else:
- self._cmd(f'systemctl stop dhclient@{ifname}.service')
-
# cleanup old config files
for file in [config_file, options_file, pid_file, lease_file]:
if os.path.isfile(file):
@@ -1074,6 +1069,10 @@ class Interface(Control):
interface setup code and provide a single point of entry when workin
on any interface. """
+ if self.debug:
+ import pprint
+ pprint.pprint(config)
+
# Cache the configuration - it will be reused inside e.g. DHCP handler
# XXX: maybe pass the option via __init__ in the future and rename this
# method to apply()?
@@ -1243,6 +1242,16 @@ class Interface(Control):
# configure port mirror
self.set_mirror()
+ # Enable/Disable of an interface must always be done at the end of the
+ # derived class to make use of the ref-counting set_admin_state()
+ # function. We will only enable the interface if 'up' was called as
+ # often as 'down'. This is required by some interface implementations
+ # as certain parameters can only be changed when the interface is
+ # in admin-down state. This ensures the link does not flap during
+ # reconfiguration.
+ state = 'down' if 'disable' in config else 'up'
+ self.set_admin_state(state)
+
# remove no longer required 802.1ad (Q-in-Q VLANs)
ifname = config['ifname']
for vif_s_id in config.get('vif_s_remove', {}):
@@ -1296,17 +1305,7 @@ class Interface(Control):
class VLANIf(Interface):
""" Specific class which abstracts 802.1q and 802.1ad (Q-in-Q) VLAN interfaces """
- default = {
- 'type': 'vlan',
- 'source_interface': '',
- 'vlan_id': '',
- 'protocol': '',
- 'ingress_qos': '',
- 'egress_qos': '',
- }
-
- options = Interface.options + \
- ['source_interface', 'vlan_id', 'protocol', 'ingress_qos', 'egress_qos']
+ iftype = 'vlan'
def remove(self):
"""
@@ -1335,11 +1334,11 @@ class VLANIf(Interface):
return
cmd = 'ip link add link {source_interface} name {ifname} type vlan id {vlan_id}'
- if self.config['protocol']:
+ if 'protocol' in self.config:
cmd += ' protocol {protocol}'
- if self.config['ingress_qos']:
+ if 'ingress_qos' in self.config:
cmd += ' ingress-qos-map {ingress_qos}'
- if self.config['egress_qos']:
+ if 'egress_qos' in self.config:
cmd += ' egress-qos-map {egress_qos}'
self._cmd(cmd.format(**self.config))
@@ -1371,22 +1370,3 @@ class VLANIf(Interface):
def set_mirror(self):
return
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py
index 8ed3d5afb..7ff0fdd0e 100644
--- a/python/vyos/ifconfig/l2tpv3.py
+++ b/python/vyos/ifconfig/l2tpv3.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -24,19 +24,7 @@ class L2TPv3If(Interface):
either hot standby or load balancing services. Additionally, link integrity
monitoring may be performed.
"""
-
- default = {
- 'type': 'l2tp',
- 'peer_tunnel_id': '',
- 'local_port': 0,
- 'remote_port': 0,
- 'encapsulation': 'udp',
- 'local_address': '',
- 'remote_address': '',
- 'session_id': '',
- 'tunnel_id': '',
- 'peer_session_id': ''
- }
+ iftype = 'l2tp'
definition = {
**Interface.definition,
**{
@@ -45,20 +33,16 @@ class L2TPv3If(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port',
- 'encapsulation', 'local_address', 'remote_address', 'session_id',
- 'peer_session_id']
def _create(self):
# create tunnel interface
cmd = 'ip l2tp add tunnel tunnel_id {tunnel_id}'
cmd += ' peer_tunnel_id {peer_tunnel_id}'
- cmd += ' udp_sport {local_port}'
- cmd += ' udp_dport {remote_port}'
+ cmd += ' udp_sport {source_port}'
+ cmd += ' udp_dport {destination_port}'
cmd += ' encap {encapsulation}'
- cmd += ' local {local_address}'
- cmd += ' remote {remote_address}'
+ cmd += ' local {source_address}'
+ cmd += ' remote {remote}'
self._cmd(cmd.format(**self.config))
# setup session
@@ -82,36 +66,15 @@ class L2TPv3If(Interface):
>>> i.remove()
"""
- if self.exists(self.config['ifname']):
+ if self.exists(self.ifname):
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
- if self.config['tunnel_id'] and self.config['session_id']:
+ if {'tunnel_id', 'session_id'} <= set(self.config):
cmd = 'ip l2tp del session tunnel_id {tunnel_id}'
cmd += ' session_id {session_id}'
self._cmd(cmd.format(**self.config))
- if self.config['tunnel_id']:
+ if 'tunnel_id' in self.config:
cmd = 'ip l2tp del tunnel tunnel_id {tunnel_id}'
self._cmd(cmd.format(**self.config))
-
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py
index 0e632d826..192c12f5c 100644
--- a/python/vyos/ifconfig/loopback.py
+++ b/python/vyos/ifconfig/loopback.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -22,9 +22,8 @@ class LoopbackIf(Interface):
uses to communicate with itself.
"""
_persistent_addresses = ['127.0.0.1/8', '::1/128']
- default = {
- 'type': 'loopback',
- }
+ iftype = 'loopback'
+
definition = {
**Interface.definition,
**{
@@ -33,9 +32,6 @@ class LoopbackIf(Interface):
'bridgeable': True,
}
}
-
- name = 'loopback'
-
def remove(self):
"""
Loopback interface can not be deleted from operating system. We can
@@ -70,13 +66,3 @@ class LoopbackIf(Interface):
# call base class
super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/macsec.py b/python/vyos/ifconfig/macsec.py
index 456686ea6..1a78d18d8 100644
--- a/python/vyos/ifconfig/macsec.py
+++ b/python/vyos/ifconfig/macsec.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
@@ -27,12 +27,7 @@ class MACsecIf(Interface):
other security solutions such as IPsec (layer 3) or TLS (layer 4), as all
those solutions are used for their own specific use cases.
"""
-
- default = {
- 'type': 'macsec',
- 'security_cipher': '',
- 'source_interface': ''
- }
+ iftype = 'macsec'
definition = {
**Interface.definition,
**{
@@ -40,8 +35,6 @@ class MACsecIf(Interface):
'prefixes': ['macsec', ],
},
}
- options = Interface.options + \
- ['security_cipher', 'source_interface']
def _create(self):
"""
@@ -49,28 +42,9 @@ class MACsecIf(Interface):
down by default.
"""
# create tunnel interface
- cmd = 'ip link add link {source_interface} {ifname} type {type}'
- cmd += ' cipher {security_cipher}'
- self._cmd(cmd.format(**self.config))
+ cmd = 'ip link add link {source_interface} {ifname} type {type}'.format(**self.config)
+ cmd += f' cipher {self.config["security"]["cipher"]}'
+ self._cmd(cmd)
# interface is always A/D down. It needs to be enabled explicitly
self.set_admin_state('down')
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py
index 2447fec77..776014bc3 100644
--- a/python/vyos/ifconfig/macvlan.py
+++ b/python/vyos/ifconfig/macvlan.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -20,13 +20,7 @@ class MACVLANIf(Interface):
"""
Abstraction of a Linux MACvlan interface
"""
-
- default = {
- 'type': 'macvlan',
- 'address': '',
- 'source_interface': '',
- 'mode': '',
- }
+ iftype = 'macvlan'
definition = {
**Interface.definition,
**{
@@ -34,39 +28,13 @@ class MACVLANIf(Interface):
'prefixes': ['peth', ],
},
}
- options = Interface.options + \
- ['source_interface', 'mode']
def _create(self):
# please do not change the order when assembling the command
- cmd = 'ip link add {ifname}'
- if self.config['source_interface']:
- cmd += ' link {source_interface}'
- cmd += ' type macvlan'
- if self.config['mode']:
- cmd += ' mode {mode}'
+ cmd = 'ip link add {ifname} link {source_interface} type {type} mode {mode}'
self._cmd(cmd.format(**self.config))
def set_mode(self, mode):
ifname = self.config['ifname']
cmd = f'ip link set dev {ifname} type macvlan mode {mode}'
return self._cmd(cmd)
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py
index 787245696..65575cf99 100644
--- a/python/vyos/ifconfig/pppoe.py
+++ b/python/vyos/ifconfig/pppoe.py
@@ -13,10 +13,8 @@
# 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/>.
-
from vyos.ifconfig.interface import Interface
-
@Interface.register
class PPPoEIf(Interface):
default = {
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 4320bf8bc..e5e1300b2 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -1,4 +1,4 @@
-# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -16,13 +16,12 @@
# 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 copy import deepcopy
-
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
def enable_to_on(value):
@@ -32,11 +31,10 @@ def enable_to_on(value):
return 'off'
raise ValueError(f'expect enable or disable but got "{value}"')
-
@Interface.register
-class _Tunnel(Interface):
+class TunnelIf(Interface):
"""
- _Tunnel: private base class for tunnels
+ Tunnel: private base class for tunnels
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/tunnel.c
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ip6tunnel.c
"""
@@ -48,16 +46,30 @@ class _Tunnel(Interface):
},
}
- default = {
- 'local' : '',
- 'remote': '',
- 'dev' : '',
- 'ttl' : '',
- 'tos' : '',
- 'key' : '',
- 'raw' : '',
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ # - https://man7.org/linux/man-pages/man8/ip-tunnel.8.html
+ mapping = {
+ 'source_address' : 'local',
+ 'source_interface' : 'dev',
+ 'remote' : 'remote',
+ 'parameters.ip.key' : 'key',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ }
+ mapping_ipv4 = {
+ 'parameters.ip.key' : 'key',
+ 'parameters.ip.no_pmtu_discovery' : 'nopmtudisc',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ }
+ mapping_ipv6 = {
+ 'parameters.ipv6.encaplimit' : 'encaplimit',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ 'parameters.ipv6.hoplimit' : 'hoplimit',
+ 'parameters.ipv6.tclass' : 'tclass',
}
- options = Interface.options + list(default.keys())
# TODO: This is surely used for more than tunnels
# TODO: could be refactored elsewhere
@@ -76,28 +88,69 @@ class _Tunnel(Interface):
},
}
}
- _create_cmd = 'ip tunnel add {ifname} mode {type}'
+
+ def __init__(self, ifname, **kargs):
+ # T3357: we do not have the 'encapsulation' in kargs when calling this
+ # class from op-mode like "show interfaces tunnel"
+ if 'encapsulation' in kargs:
+ self.iftype = kargs['encapsulation']
+ # The gretap interface has the possibility to act as L2 bridge
+ if self.iftype in ['gretap', 'ip6gretap']:
+ # no multicast, ttl or tos for gretap
+ self.definition = {
+ **TunnelIf.definition,
+ **{
+ 'bridgeable': True,
+ },
+ }
+
+ super().__init__(ifname, **kargs)
def _create(self):
- # add " option-name option-name-value ..." for all options set
- options = ' '.join(['{} {}'.format(k, self.config[k])
- for k,v in self.config.items() if v and k not in
- ['ifname', 'type', 'raw']])
- if 'raw' in self.config:
- options += ' ' + ' '.join(self.config['raw'])
- self._cmd('{} {}'.format(self._create_cmd.format(**self.config), options))
- self.set_admin_state('down')
+ if self.config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
+ mapping = { **self.mapping, **self.mapping_ipv6 }
+ else:
+ mapping = { **self.mapping, **self.mapping_ipv4 }
+
+ cmd = 'ip tunnel add {ifname} mode {encapsulation}'
+ if self.iftype in ['gretap', 'ip6gretap']:
+ cmd = 'ip link add name {ifname} type {encapsulation}'
+ for vyos_key, iproute2_key in mapping.items():
+ # dict_search will return an empty dict "{}" for valueless nodes like
+ # "parameters.nolearning" - thus we need to test the nodes existence
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
- def change_options(self):
- change = 'ip tunnel change {ifname} mode {type}'
+ self.set_admin_state('down')
- # add " option-name option-name-value ..." for all options set
- options = ' '.join(['{} {}'.format(k, self.config[k])
- for k,v in self.config.items() if v and k not in
- ['ifname', 'type', 'raw']])
- if 'raw' in self.config:
- options += ' ' + ' '.join(self.config['raw'])
- self._cmd('{} {}'.format(change.format(**self.config), options))
+ def _change_options(self):
+ # gretap interfaces do not support changing any parameter
+ if self.iftype in ['gretap', 'ip6gretap']:
+ return
+
+ if self.config['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
+ mapping = { **self.mapping, **self.mapping_ipv6 }
+ else:
+ mapping = { **self.mapping, **self.mapping_ipv4 }
+
+ cmd = 'ip tunnel change {ifname} mode {encapsulation}'
+ for vyos_key, iproute2_key in mapping.items():
+ # dict_search will return an empty dict "{}" for valueless nodes like
+ # "parameters.nolearning" - thus we need to test the nodes existence
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
def get_mac(self):
"""
@@ -128,172 +181,8 @@ class _Tunnel(Interface):
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. """
+ # Adjust iproute2 tunnel parameters if necessary
+ self._change_options()
# call base class first
super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
-class GREIf(_Tunnel):
- """
- GRE: Generic Routing Encapsulation
-
- For more information please refer to:
- RFC1701, RFC1702, RFC2784
- https://tools.ietf.org/html/rfc2784
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre.c
- """
-
- default = {
- **_Tunnel.default,
- **{
- 'type': 'gre',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- },
- }
-
-# GreTap also called GRE Bridge
-class GRETapIf(_Tunnel):
- """
- GRETapIF: GreIF using TAP instead of TUN
-
- https://en.wikipedia.org/wiki/TUN/TAP
- """
- # no multicast, ttl or tos for gretap
- definition = {
- **_Tunnel.definition,
- **{
- 'bridgeable': True,
- },
- }
- default = {
- 'type': 'gretap',
- 'local': '',
- 'remote': '',
- 'dev': '',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- }
-
- _create_cmd = 'ip link add name {ifname} type {type}'
-
- def change_options(self):
- pass
-
-class IP6GREIf(_Tunnel):
- """
- IP6Gre: IPv6 Support for Generic Routing Encapsulation (GRE)
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc7676
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_gre6.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ip6gre',
- 'encaplimit': '',
- 'hoplimit': '',
- 'tclass': '',
- 'flowlabel': '',
- },
- }
-
-class IPIPIf(_Tunnel):
- """
- IPIP: IP Encapsulation within IP
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc2003
- """
- # IPIP does not allow to pass multicast, unlike GRE
- # but the interface itself can be set with multicast
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ipip',
- 'raw' : ['pmtudisc'], # parameters that we can pass raw to ip command
- },
- }
-
-class IPIP6If(_Tunnel):
- """
- IPIP6: IPv4 over IPv6 tunnel
-
- For more information please refer to:
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_ip6tnl.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ipip6',
- 'encaplimit': '',
- 'hoplimit': '',
- 'tclass': '',
- 'flowlabel': '',
- },
- }
-
-class IP6IP6If(IPIP6If):
- """
- IP6IP6: IPv6 over IPv6 tunnel
-
- For more information please refer to:
- https://tools.ietf.org/html/rfc2473
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'ip6ip6',
- },
- }
-
-
-class SitIf(_Tunnel):
- """
- Sit: Simple Internet Transition
-
- For more information please refer to:
- https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/link_iptnl.c
- """
- default = {
- **_Tunnel.default,
- **{
- 'type': 'sit',
- },
- }
-
-class Sit6RDIf(SitIf):
- """
- Sit6RDIf: Simple Internet Transition with 6RD
-
- https://en.wikipedia.org/wiki/IPv6_rapid_deployment
- """
- # TODO: check if key can really be used with 6RD
- default = {
- **_Tunnel.default,
- **{
- 'type': '6rd',
- '6rd_prefix' : '',
- '6rd_relay_prefix' : '',
- },
- }
-
- def _create(self):
- # do not call _Tunnel.create, building fully here
-
- create = 'ip tunnel add {ifname} mode {type} remote {remote}'
- self._cmd(create.format(**self.config))
- self.set_interface('state','down')
-
- set6rd = 'ip tunnel 6rd dev {ifname} 6rd-prefix {6rd-prefix}'
- if '6rd-relay-prefix' in self.config:
- set6rd += ' 6rd-relay-prefix {6rd-relay-prefix}'
- self._cmd(set6rd.format(**self.config))
diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py
index d0745898c..e2090c889 100644
--- a/python/vyos/ifconfig/vti.py
+++ b/python/vyos/ifconfig/vti.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 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
@@ -17,9 +17,7 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class VTIIf(Interface):
- default = {
- 'type': 'vti',
- }
+ iftype = 'vti'
definition = {
**Interface.definition,
**{
diff --git a/python/vyos/ifconfig/vtun.py b/python/vyos/ifconfig/vtun.py
index 99a592b3e..6fb414e56 100644
--- a/python/vyos/ifconfig/vtun.py
+++ b/python/vyos/ifconfig/vtun.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
@@ -17,10 +17,7 @@ from vyos.ifconfig.interface import Interface
@Interface.register
class VTunIf(Interface):
- default = {
- 'type': 'vtun',
- 'device_type': 'tun',
- }
+ iftype = 'vtun'
definition = {
**Interface.definition,
**{
@@ -29,7 +26,6 @@ class VTunIf(Interface):
'bridgeable': True,
},
}
- options = Interface.options + ['device_type']
def _create(self):
""" Depending on OpenVPN operation mode the interface is created
@@ -51,22 +47,3 @@ class VTunIf(Interface):
def del_addr(self, addr):
# IP addresses are managed by OpenVPN daemon
pass
-
- 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. """
-
- # call base class first
- super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index ad1f605ed..d73fb47b8 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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,7 +14,8 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from vyos import ConfigError
-from vyos.ifconfig.interface import Interface
+from vyos.ifconfig import Interface
+from vyos.util import dict_search
@Interface.register
class VXLANIf(Interface):
@@ -38,16 +39,7 @@ class VXLANIf(Interface):
https://www.kernel.org/doc/Documentation/networking/vxlan.txt
"""
- default = {
- 'type': 'vxlan',
- 'group': '',
- 'port': 8472, # The Linux implementation of VXLAN pre-dates
- # the IANA's selection of a standard destination port
- 'remote': '',
- 'source_address': '',
- 'source_interface': '',
- 'vni': 0
- }
+ iftype = 'vxlan'
definition = {
**Interface.definition,
**{
@@ -56,60 +48,34 @@ class VXLANIf(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['group', 'remote', 'source_interface', 'port', 'vni', 'source_address']
-
- mapping = {
- 'ifname': 'add',
- 'vni': 'id',
- 'port': 'dstport',
- 'source_address': 'local',
- 'source_interface': 'dev',
- }
def _create(self):
- cmdline = ['ifname', 'type', 'vni', 'port']
-
- if self.config['source_address']:
- cmdline.append('source_address')
-
- if self.config['remote']:
- cmdline.append('remote')
-
- if self.config['group'] or self.config['source_interface']:
- if self.config['group'] and self.config['source_interface']:
- cmdline.append('group')
- cmdline.append('source_interface')
- else:
- ifname = self.config['ifname']
- raise ConfigError(
- f'VXLAN "{ifname}" is missing mandatory underlay multicast'
- 'group or source interface for a multicast network.')
-
- cmd = 'ip link'
- for key in cmdline:
- value = self.config.get(key, '')
- if not value:
- continue
- cmd += ' {} {}'.format(self.mapping.get(key, key), value)
-
- self._cmd(cmd)
-
- 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. """
-
- # call base class first
- super().update(config)
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ mapping = {
+ 'source_address' : 'local',
+ 'source_interface' : 'dev',
+ 'remote' : 'remote',
+ 'group' : 'group',
+ 'parameters.ip.dont_fragment': 'df set',
+ 'parameters.ip.tos' : 'tos',
+ 'parameters.ip.ttl' : 'ttl',
+ 'parameters.ipv6.flowlabel' : 'flowlabel',
+ 'parameters.nolearning' : 'nolearning',
+ }
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
+ cmd = 'ip link add {ifname} type {type} id {vni} dstport {port}'
+ for vyos_key, iproute2_key in mapping.items():
+ # dict_search will return an empty dict "{}" for valueless nodes like
+ # "parameters.nolearning" - thus we need to test the nodes existence
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
+ # interface is always A/D down. It needs to be enabled explicitly
+ self.set_admin_state('down')
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index 9ee798ee8..e5b9c4408 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2019-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
@@ -148,18 +148,7 @@ class WireGuardOperational(Operational):
@Interface.register
class WireGuardIf(Interface):
OperationalClass = WireGuardOperational
-
- default = {
- 'type': 'wireguard',
- 'port': 0,
- 'private_key': None,
- 'pubkey': None,
- 'psk': '',
- 'allowed_ips': [],
- 'fwmark': 0x00,
- 'endpoint': None,
- 'keepalive': 0
- }
+ iftype = 'wireguard'
definition = {
**Interface.definition,
**{
@@ -168,9 +157,6 @@ class WireGuardIf(Interface):
'bridgeable': False,
}
}
- options = Interface.options + \
- ['port', 'private_key', 'pubkey', 'psk',
- 'allowed_ips', 'fwmark', 'endpoint', 'keepalive']
def get_mac(self):
"""
@@ -261,14 +247,3 @@ class WireGuardIf(Interface):
# call base class
super().update(config)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py
index 37703d242..748b6e02d 100644
--- a/python/vyos/ifconfig/wireless.py
+++ b/python/vyos/ifconfig/wireless.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
@@ -20,11 +20,7 @@ class WiFiIf(Interface):
"""
Handle WIFI/WLAN interfaces.
"""
-
- default = {
- 'type': 'wifi',
- 'phy': 'phy0'
- }
+ iftype = 'wifi'
definition = {
**Interface.definition,
**{
@@ -33,14 +29,10 @@ class WiFiIf(Interface):
'bridgeable': True,
}
}
- options = Interface.options + \
- ['phy', 'op_mode']
-
def _create(self):
# all interfaces will be added in monitor mode
- cmd = 'iw phy {phy} interface add {ifname} type monitor' \
- .format(**self.config)
- self._cmd(cmd)
+ cmd = 'iw phy {physical_device} interface add {ifname} type monitor'
+ self._cmd(cmd.format(**self.config))
# wireless interface is administratively down by default
self.set_admin_state('down')
@@ -71,24 +63,3 @@ class WiFiIf(Interface):
# re-add ourselves to any bridge we might have fallen out of
if bridge_member:
self.add_to_bridge(bridge_member)
-
- # Enable/Disable of an interface must always be done at the end of the
- # derived class to make use of the ref-counting set_admin_state()
- # function. We will only enable the interface if 'up' was called as
- # often as 'down'. This is required by some interface implementations
- # as certain parameters can only be changed when the interface is
- # in admin-down state. This ensures the link does not flap during
- # reconfiguration.
- state = 'down' if 'disable' in config else 'up'
- self.set_admin_state(state)
-
-
-@Interface.register
-class WiFiModemIf(WiFiIf):
- definition = {
- **WiFiIf.definition,
- **{
- 'section': 'wirelessmodem',
- 'prefixes': ['wlm', ],
- }
- }
diff --git a/python/vyos/remote.py b/python/vyos/remote.py
index 3f46d979b..47af9d3a6 100644
--- a/python/vyos/remote.py
+++ b/python/vyos/remote.py
@@ -1,4 +1,4 @@
-# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 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
@@ -13,74 +13,64 @@
# 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 sys
import os
-import re
-import fileinput
+import sys
+import tempfile
+from ftplib import FTP
+import urllib.parse
+import urllib.request
from vyos.util import cmd
-from vyos.util import DEVNULL
-
-
-def check_and_add_host_key(host_name):
- """
- Filter host keys and prompt for adding key to known_hosts file, if
- needed.
- """
- known_hosts = '{}/.ssh/known_hosts'.format(os.getenv('HOME'))
- if not os.path.exists(known_hosts):
- mode = 0o600
- os.mknod(known_hosts, 0o600)
-
- keyscan_cmd = 'ssh-keyscan -t rsa {}'.format(host_name)
-
- try:
- host_key = cmd(keyscan_cmd, stderr=DEVNULL)
- except OSError:
- sys.exit("Can not get RSA host key")
-
- # libssh2 (jessie; stretch) does not recognize ec host keys, and curl
- # will fail with error 51 if present in known_hosts file; limit to rsa.
- usable_keys = False
- offending_keys = []
- for line in fileinput.input(known_hosts, inplace=True):
- if host_name in line and 'ssh-rsa' in line:
- if line.split()[-1] != host_key.split()[-1]:
- offending_keys.append(line)
- continue
- else:
- usable_keys = True
- if host_name in line and not 'ssh-rsa' in line:
- continue
-
- sys.stdout.write(line)
-
- if usable_keys:
- return
-
- if offending_keys:
- print("Host key has changed!")
- print("If you trust the host key fingerprint below, continue.")
-
- fingerprint_cmd = 'ssh-keygen -lf /dev/stdin'
- try:
- fingerprint = cmd(fingerprint_cmd, stderr=DEVNULL, input=host_key)
- except OSError:
- sys.exit("Can not get RSA host key fingerprint.")
-
- print("RSA host key fingerprint is {}".format(fingerprint.split()[1]))
- response = input("Do you trust this host? [y]/n ")
-
- if not response or response == 'y':
- with open(known_hosts, 'a+') as f:
- print("Adding {} to the list of known"
- " hosts.".format(host_name))
- f.write(host_key)
- else:
- sys.exit("Host not trusted")
-
-def get_remote_config(remote_file):
- """ Invoke curl to download remote (config) file.
+from paramiko import SSHClient
+
+def upload_ftp(local_path, hostname, remote_path,\
+ username='anonymous', password='', port=21):
+ with open(local_path, 'rb') as file:
+ with FTP() as conn:
+ conn.connect(hostname, port)
+ conn.login(username, password)
+ conn.storbinary(f'STOR {remote_path}', file)
+
+def download_ftp(local_path, hostname, remote_path,\
+ username='anonymous', password='', port=21):
+ with open(local_path, 'wb') as file:
+ with FTP() as conn:
+ conn.connect(hostname, port)
+ conn.login(username, password)
+ conn.retrbinary(f'RETR {remote_path}', file.write)
+
+def upload_sftp(local_path, hostname, remote_path,\
+ username=None, password=None, port=22):
+ with SSHClient() as ssh:
+ ssh.load_system_host_keys()
+ ssh.connect(hostname, port, username, password)
+ with ssh.open_sftp() as sftp:
+ sftp.put(local_path, remote_path)
+
+def download_sftp(local_path, hostname, remote_path,\
+ username, password=None, port=22):
+ with SSHClient() as ssh:
+ ssh.load_system_host_keys()
+ ssh.connect(hostname, port, username, password)
+ with ssh.open_sftp() as sftp:
+ sftp.get(remote_path, local_path)
+
+def upload_tftp(local_path, hostname, remote_path, port=69):
+ with open(local_path, 'rb') as file:
+ cmd(f'curl -s -T - tftp://{hostname}:{port}/{remote_path}', stderr=None, input=file.read())
+
+def download_tftp(local_path, hostname, remote_path, port=69):
+ with open(local_path, 'wb') as file:
+ file.write(cmd(f'curl -s tftp://{hostname}:{port}/{remote_path}', stderr=None))
+
+
+def download_http(urlstring, local_path):
+ with open(local_path, 'wb') as file:
+ with urllib.request.urlopen(urlstring) as response:
+ file.write(response.read())
+
+def get_remote_config(urlstring: str) -> bytes:
+ """Download remote (config) file and return the contents.
Args:
remote file URI:
@@ -88,56 +78,29 @@ def get_remote_config(remote_file):
sftp://<user>[:<passwd>]@<host>/<file>
http://<host>/<file>
https://<host>/<file>
- ftp://<user>[:<passwd>]@<host>/<file>
+ ftp://[<user>[:<passwd>]@]<host>/<file>
tftp://<host>/<file>
"""
- request = dict.fromkeys(['protocol', 'user', 'host', 'file'])
- protocols = ['scp', 'sftp', 'http', 'https', 'ftp', 'tftp']
- or_protocols = '|'.join(protocols)
-
- request_match = re.match(r'(' + or_protocols + r')://(.*?)(/.*)',
- remote_file)
- if request_match:
- (request['protocol'], request['host'],
- request['file']) = request_match.groups()
- else:
- print("Malformed URI")
- sys.exit(1)
-
- user_match = re.search(r'(.*)@(.*)', request['host'])
- if user_match:
- request['user'] = user_match.groups()[0]
- request['host'] = user_match.groups()[1]
-
- remote_file = '{0}://{1}{2}'.format(request['protocol'], request['host'], request['file'])
-
- if request['protocol'] in ('scp', 'sftp'):
- check_and_add_host_key(request['host'])
-
- redirect_opt = ''
-
- if request['protocol'] in ('http', 'https'):
- redirect_opt = '-L'
- # Try header first, and look for 'OK' or 'Moved' codes:
- curl_cmd = 'curl {0} -q -I {1}'.format(redirect_opt, remote_file)
- try:
- curl_output = cmd(curl_cmd)
- except OSError:
- sys.exit(1)
-
- return_vals = re.findall(r'^HTTP\/\d+\.?\d\s+(\d+)\s+(.*)$',
- curl_output, re.MULTILINE)
- for val in return_vals:
- if int(val[0]) not in [200, 301, 302]:
- print('HTTP error: {0} {1}'.format(*val))
- sys.exit(1)
-
- if request['user']:
- curl_cmd = 'curl -# -u {0} {1}'.format(request['user'], remote_file)
- else:
- curl_cmd = 'curl {0} -# {1}'.format(redirect_opt, remote_file)
-
+ url = urllib.parse.urlparse(urlstring)
+ temp = tempfile.NamedTemporaryFile(delete=False).name
try:
- return cmd(curl_cmd, stderr=None)
- except OSError:
- return None
+ if url.scheme == 'http' or url.scheme == 'https':
+ download_http(urlstring, temp)
+ elif url.scheme == 'ftp':
+ username = url.username if url.username else 'anonymous'
+ download_ftp(temp, url.hostname, url.path, username, url.password)
+ elif url.scheme == 'sftp' or url.scheme == 'scp':
+ # None means we don't want to use password authentication.
+ # An empty string (what urlparse returns when a password doesn't
+ # exist in the URL) means the password is an empty string.
+ password = url.password if url.password else None
+ download_sftp(temp, url.hostname, url.path, url.username, password)
+ elif url.scheme == 'tftp':
+ download_tftp(temp, url.path, url.hostname, url.path)
+ else:
+ sys.exit('Unsupported URL scheme')
+ with open(temp, 'r') as file:
+ config = file.read()
+ return config
+ finally:
+ os.remove(temp)
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 527384d0b..85e4d12b3 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -131,6 +131,13 @@ def address_from_cidr(prefix):
from ipaddress import ip_network
return str(ip_network(prefix).network_address)
+@register_filter('bracketize_ipv6')
+def bracketize_ipv6(address):
+ """ Place a passed IPv6 address into [] brackets, do nothing for IPv4 """
+ if is_ipv6(address):
+ return f'[{address}]'
+ return address
+
@register_filter('netmask_from_cidr')
def netmask_from_cidr(prefix):
""" Take CIDR prefix and convert the prefix length to a "subnet mask".
@@ -288,7 +295,6 @@ def compare_netmask(netmask1, netmask2):
except:
return False
-
@register_filter('isc_static_route')
def isc_static_route(subnet, router):
# https://ercpe.de/blog/pushing-static-routes-with-isc-dhcp-server
@@ -316,3 +322,22 @@ def is_file(filename):
if os.path.exists(filename):
return os.path.isfile(filename)
return False
+
+@register_filter('get_dhcp_router')
+def get_dhcp_router(interface):
+ """ Static routes can point to a router received by a DHCP reply. This
+ helper is used to get the current default router from the DHCP reply.
+
+ Returns False of no router is found, returns the IP address as string if
+ a router is found.
+ """
+ interface = interface.replace('.', '_')
+ lease_file = f'/var/lib/dhcp/dhclient_{interface}.leases'
+ if not os.path.exists(lease_file):
+ return None
+
+ from vyos.util import read_file
+ for line in read_file(lease_file).splitlines():
+ if 'option routers' in line:
+ (_, _, address) = line.split()
+ return address.rstrip(';')
diff --git a/python/vyos/util.py b/python/vyos/util.py
index ab5029c92..e4de56cdb 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -645,3 +645,26 @@ def dict_search(path, dict):
for p in parts[:-1]:
c = c.get(p, {})
return c.get(parts[-1], None)
+
+def get_interface_config(interface):
+ """ Returns the used encapsulation protocol for given interface.
+ If interface does not exist, None is returned.
+ """
+ if not os.path.exists(f'/sys/class/net/{interface}'):
+ return None
+ from json import loads
+ tmp = loads(cmd(f'ip -d -j link show {interface}'))[0]
+ return tmp
+
+def get_all_vrfs():
+ """ Return a dictionary of all system wide known VRF instances """
+ from json import loads
+ tmp = loads(cmd('ip -j vrf list'))
+ # Result is of type [{"name":"red","table":1000},{"name":"blue","table":2000}]
+ # so we will re-arrange it to a more nicer representation:
+ # {'red': {'table': 1000}, 'blue': {'table': 2000}}
+ data = {}
+ for entry in tmp:
+ name = entry.pop('name')
+ data[name] = entry
+ return data
diff --git a/smoketest/configs/azure-bgp-gateway b/smoketest/configs/azure-bgp-gateway
new file mode 100644
index 000000000..b3f5e9edc
--- /dev/null
+++ b/smoketest/configs/azure-bgp-gateway
@@ -0,0 +1,435 @@
+firewall {
+ all-ping enable
+ broadcast-ping disable
+ config-trap disable
+ ipv6-receive-redirects disable
+ ipv6-src-route disable
+ ip-src-route disable
+ log-martians disable
+ options {
+ interface vti31 {
+ adjust-mss 1350
+ }
+ interface vti32 {
+ adjust-mss 1350
+ }
+ interface vti41 {
+ adjust-mss 1350
+ }
+ interface vti42 {
+ adjust-mss 1350
+ }
+ interface vti51 {
+ adjust-mss 1350
+ }
+ interface vti52 {
+ adjust-mss 1350
+ }
+ }
+ receive-redirects disable
+ send-redirects enable
+ source-validation disable
+ syn-cookies enable
+ twa-hazards-protection disable
+}
+high-availability {
+ vrrp {
+ group DMZ-VLAN-3962 {
+ interface eth1
+ preempt-delay 180
+ priority 200
+ virtual-address 192.168.34.36/27
+ vrid 62
+ }
+ }
+}
+interfaces {
+ ethernet eth0 {
+ address 192.0.2.189/27
+ duplex auto
+ smp-affinity auto
+ speed auto
+ }
+ ethernet eth1 {
+ address 192.168.34.37/27
+ duplex auto
+ smp-affinity auto
+ speed auto
+ }
+ loopback lo {
+ }
+ vti vti31 {
+ }
+ vti vti32 {
+ }
+ vti vti41 {
+ }
+ vti vti42 {
+ }
+ vti vti51 {
+ }
+ vti vti52 {
+ }
+}
+policy {
+ prefix-list AZURE-BGP-IPv4-in {
+ description "Prefixes received from Azure"
+ rule 100 {
+ action permit
+ le 32
+ prefix 100.64.0.0/10
+ }
+ }
+ prefix-list ONPREM-BGP-IPv4-out {
+ description "Prefixes allowed to be announced into Azure"
+ rule 100 {
+ action permit
+ prefix 10.0.0.0/8
+ }
+ rule 200 {
+ action permit
+ prefix 172.16.0.0/12
+ }
+ rule 300 {
+ action permit
+ prefix 192.168.0.0/16
+ }
+ }
+}
+protocols {
+ bgp 65522 {
+ address-family {
+ ipv4-unicast {
+ network 10.0.0.0/8 {
+ }
+ network 172.16.0.0/12 {
+ }
+ network 192.168.0.0/16 {
+ }
+ }
+ }
+ neighbor 100.66.8.36 {
+ peer-group AZURE
+ remote-as 64517
+ }
+ neighbor 100.66.8.37 {
+ peer-group AZURE
+ remote-as 64517
+ }
+ neighbor 100.66.24.36 {
+ peer-group AZURE
+ remote-as 64513
+ }
+ neighbor 100.66.24.37 {
+ peer-group AZURE
+ remote-as 64513
+ }
+ neighbor 100.66.40.36 {
+ peer-group AZURE
+ remote-as 64515
+ }
+ neighbor 100.66.40.37 {
+ peer-group AZURE
+ remote-as 64515
+ }
+ neighbor 192.168.34.38 {
+ address-family {
+ ipv4-unicast {
+ nexthop-self
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ capability {
+ dynamic
+ }
+ password VyOSR0xx123
+ remote-as 65522
+ update-source eth1
+ }
+ peer-group AZURE {
+ address-family {
+ ipv4-unicast {
+ maximum-prefix 50
+ prefix-list {
+ export ONPREM-BGP-IPv4-out
+ import AZURE-BGP-IPv4-in
+ }
+ }
+ }
+ ebgp-multihop 2
+ update-source eth1
+ }
+ timers {
+ holdtime 30
+ keepalive 5
+ }
+ }
+ static {
+ interface-route 100.66.8.36/32 {
+ next-hop-interface vti31 {
+ }
+ next-hop-interface vti32 {
+ }
+ }
+ interface-route 100.66.8.37/32 {
+ next-hop-interface vti31 {
+ }
+ next-hop-interface vti32 {
+ }
+ }
+ interface-route 100.66.24.36/32 {
+ next-hop-interface vti41 {
+ }
+ next-hop-interface vti42 {
+ }
+ }
+ interface-route 100.66.24.37/32 {
+ next-hop-interface vti41 {
+ }
+ next-hop-interface vti42 {
+ }
+ }
+ interface-route 100.66.40.36/32 {
+ next-hop-interface vti51 {
+ }
+ next-hop-interface vti52 {
+ }
+ }
+ interface-route 100.66.40.37/32 {
+ next-hop-interface vti51 {
+ }
+ next-hop-interface vti52 {
+ }
+ }
+ route 0.0.0.0/0 {
+ next-hop 192.168.34.33 {
+ }
+ }
+ route 51.105.0.0/16 {
+ next-hop 192.0.2.161 {
+ }
+ }
+ route 52.143.0.0/16 {
+ next-hop 192.0.2.161 {
+ }
+ }
+ route 195.137.175.0/24 {
+ next-hop 192.0.2.161 {
+ }
+ }
+ route 212.23.159.0/26 {
+ next-hop 192.0.2.161 {
+ }
+ }
+ }
+}
+service {
+ ssh {
+ disable-host-validation
+ port 22
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ domain-name vyos.net
+ flow-accounting {
+ interface eth1
+ interface vti31
+ interface vti32
+ interface vti41
+ interface vti42
+ interface vti51
+ interface vti52
+ netflow {
+ server 10.0.1.1 {
+ port 2055
+ }
+ source-ip 192.168.34.37
+ version 10
+ }
+ syslog-facility daemon
+ }
+ host-name azure-gw-01
+ login {
+ radius-server 192.0.2.253 {
+ port 1812
+ secret secret1234
+ timeout 2
+ }
+ radius-server 192.0.2.254 {
+ port 1812
+ secret secret1234
+ timeout 2
+ }
+ radius-source-address 192.168.34.37
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ name-server 192.0.2.254
+ ntp {
+ server 192.0.2.254 {
+ }
+ }
+ syslog {
+ global {
+ archive {
+ file 10
+ size 20480
+ }
+ facility all {
+ level info
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ host 10.0.9.188 {
+ facility all {
+ level info
+ protocol udp
+ }
+ }
+ }
+ time-zone Europe/Berlin
+}
+vpn {
+ ipsec {
+ esp-group ESP-AZURE {
+ compression disable
+ lifetime 27000
+ mode tunnel
+ pfs disable
+ proposal 1 {
+ encryption aes256
+ hash sha1
+ }
+ }
+ ike-group IKE-AZURE {
+ close-action none
+ dead-peer-detection {
+ action restart
+ interval 2
+ timeout 15
+ }
+ ikev2-reauth no
+ key-exchange ikev2
+ lifetime 27000
+ proposal 1 {
+ dh-group 2
+ encryption aes256
+ hash sha1
+ }
+ }
+ ipsec-interfaces {
+ interface eth0
+ }
+ logging {
+ log-level 2
+ log-modes ike
+ }
+ site-to-site {
+ peer 51.105.0.2 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti51
+ esp-group ESP-AZURE
+ }
+ }
+ peer 51.105.0.3 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti52
+ esp-group ESP-AZURE
+ }
+ }
+ peer 51.105.0.246 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti32
+ esp-group ESP-AZURE
+ }
+ }
+ peer 51.105.0.247 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti31
+ esp-group ESP-AZURE
+ }
+ }
+ peer 51.105.0.18 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti42
+ esp-group ESP-AZURE
+ }
+ }
+ peer 51.105.0.19 {
+ authentication {
+ mode pre-shared-secret
+ pre-shared-secret averysecretpsktowardsazure
+ }
+ connection-type respond
+ ike-group IKE-AZURE
+ ikev2-reauth inherit
+ local-address 192.0.2.189
+ vti {
+ bind vti41
+ esp-group ESP-AZURE
+ }
+ }
+ }
+ }
+}
+
+
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
+/* Release version: 1.2.5 */
diff --git a/smoketest/configs/bgp-bfd-communities b/smoketest/configs/bgp-bfd-communities
new file mode 100644
index 000000000..3b3056a51
--- /dev/null
+++ b/smoketest/configs/bgp-bfd-communities
@@ -0,0 +1,533 @@
+interfaces {
+ ethernet eth0 {
+ address 192.0.2.100/25
+ address 2001:db8::ffff/64
+ }
+ loopback lo {
+ }
+}
+policy {
+ large-community-list ANYCAST_ALL {
+ rule 10 {
+ action permit
+ description "Allow all anycast from anywhere"
+ regex "4242420696:100:.*"
+ }
+ }
+ large-community-list ANYCAST_INT {
+ rule 10 {
+ action permit
+ description "Allow all anycast from int"
+ regex 4242420696:100:1
+ }
+ }
+ prefix-list BGP-BACKBONE-IN {
+ description "Inbound backbone routes from other sites"
+ rule 10 {
+ action deny
+ description "Block default route"
+ prefix 0.0.0.0/0
+ }
+ rule 20 {
+ action deny
+ description "Block int primary"
+ ge 21
+ prefix 192.168.0.0/20
+ }
+ rule 30 {
+ action deny
+ description "Block loopbacks"
+ ge 25
+ prefix 192.168.253.0/24
+ }
+ rule 40 {
+ action deny
+ description "Block backbone peering"
+ ge 25
+ prefix 192.168.254.0/24
+ }
+ rule 999 {
+ action permit
+ description "Allow everything else"
+ ge 1
+ prefix 0.0.0.0/0
+ }
+ }
+ prefix-list BGP-BACKBONE-OUT {
+ description "Outbound backbone routes to other sites"
+ rule 10 {
+ action permit
+ description "Int primary"
+ ge 23
+ prefix 192.168.0.0/20
+ }
+ }
+ prefix-list GLOBAL {
+ description "Globally redistributed routes"
+ rule 10 {
+ action permit
+ prefix 192.168.100.1/32
+ }
+ rule 20 {
+ action permit
+ prefix 192.168.7.128/25
+ }
+ }
+ prefix-list6 BGP-BACKBONE-IN-V6 {
+ description "Inbound backbone routes from other sites"
+ rule 10 {
+ action deny
+ description "Block default route"
+ prefix ::/0
+ }
+ rule 20 {
+ action deny
+ description "Block int primary"
+ ge 53
+ prefix fd52:d62e:8011::/52
+ }
+ rule 30 {
+ action deny
+ description "Block peering and stuff"
+ ge 53
+ prefix fd52:d62e:8011:f000::/52
+ }
+ rule 999 {
+ action permit
+ description "Allow everything else"
+ ge 1
+ prefix ::/0
+ }
+ }
+ prefix-list6 BGP-BACKBONE-OUT-V6 {
+ description "Outbound backbone routes to other sites"
+ rule 10 {
+ action permit
+ ge 64
+ prefix fd52:d62e:8011::/52
+ }
+ }
+ prefix-list6 GLOBAL-V6 {
+ description "Globally redistributed routes"
+ rule 10 {
+ action permit
+ ge 64
+ prefix fd52:d62e:8011:2::/63
+ }
+ }
+ route-map BGP-REDISTRIBUTE {
+ rule 10 {
+ action permit
+ description "Prepend AS and allow VPN and modem"
+ match {
+ ip {
+ address {
+ prefix-list GLOBAL
+ }
+ }
+ }
+ set {
+ as-path-prepend 4242420666
+ }
+ }
+ rule 20 {
+ action permit
+ description "Allow VPN"
+ match {
+ ipv6 {
+ address {
+ prefix-list GLOBAL-V6
+ }
+ }
+ }
+ }
+ }
+ route-map BGP-BACKBONE-IN {
+ rule 10 {
+ action permit
+ match {
+ ip {
+ address {
+ prefix-list BGP-BACKBONE-IN
+ }
+ }
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ ipv6 {
+ address {
+ prefix-list BGP-BACKBONE-IN-V6
+ }
+ }
+ }
+ }
+ rule 30 {
+ action permit
+ match {
+ large-community {
+ large-community-list ANYCAST_ALL
+ }
+ }
+ }
+ }
+ route-map BGP-BACKBONE-OUT {
+ rule 10 {
+ action permit
+ match {
+ ip {
+ address {
+ prefix-list BGP-BACKBONE-OUT
+ }
+ }
+ }
+ }
+ rule 20 {
+ action permit
+ match {
+ ipv6 {
+ address {
+ prefix-list BGP-BACKBONE-OUT-V6
+ }
+ }
+ }
+ }
+ rule 30 {
+ action permit
+ match {
+ large-community {
+ large-community-list ANYCAST_INT
+ }
+ }
+ set {
+ as-path-prepend 4242420666
+ }
+ }
+ }
+}
+protocols {
+ bfd {
+ peer 192.168.253.1 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address 192.168.253.3
+ }
+ }
+ peer 192.168.253.2 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address 192.168.253.3
+ }
+ }
+ peer 192.168.253.6 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address 192.168.253.3
+ }
+ }
+ peer 192.168.253.7 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address 192.168.253.3
+ }
+ }
+ peer 192.168.253.12 {
+ interval {
+ receive 100
+ transmit 100
+ }
+ multihop
+ source {
+ address 192.168.253.3
+ }
+ }
+ peer fd52:d62e:8011:fffe:192:168:253:1 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address fd52:d62e:8011:fffe:192:168:253:3
+ }
+ }
+ peer fd52:d62e:8011:fffe:192:168:253:2 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address fd52:d62e:8011:fffe:192:168:253:3
+ }
+ }
+ peer fd52:d62e:8011:fffe:192:168:253:6 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address fd52:d62e:8011:fffe:192:168:253:3
+ }
+ }
+ peer fd52:d62e:8011:fffe:192:168:253:7 {
+ interval {
+ receive 50
+ transmit 50
+ }
+ multihop
+ source {
+ address fd52:d62e:8011:fffe:192:168:253:3
+ }
+ }
+ peer fd52:d62e:8011:fffe:192:168:253:12 {
+ interval {
+ receive 100
+ transmit 100
+ }
+ multihop
+ source {
+ address fd52:d62e:8011:fffe:192:168:253:3
+ }
+ }
+ }
+ bgp 4242420666 {
+ address-family {
+ ipv4-unicast {
+ redistribute {
+ connected {
+ route-map BGP-REDISTRIBUTE
+ }
+ static {
+ route-map BGP-REDISTRIBUTE
+ }
+ }
+ }
+ ipv6-unicast {
+ redistribute {
+ connected {
+ route-map BGP-REDISTRIBUTE
+ }
+ }
+ }
+ }
+ neighbor 192.168.253.1 {
+ peer-group INT
+ }
+ neighbor 192.168.253.2 {
+ peer-group INT
+ }
+ neighbor 192.168.253.6 {
+ peer-group DAL13
+ }
+ neighbor 192.168.253.7 {
+ peer-group DAL13
+ }
+ neighbor 192.168.253.12 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export BGP-BACKBONE-OUT
+ import BGP-BACKBONE-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd {
+ }
+ ebgp-multihop 2
+ remote-as 4242420669
+ update-source dum0
+ }
+ neighbor fd52:d62e:8011:fffe:192:168:253:1 {
+ address-family {
+ ipv6-unicast {
+ peer-group INTv6
+ }
+ }
+ }
+ neighbor fd52:d62e:8011:fffe:192:168:253:2 {
+ address-family {
+ ipv6-unicast {
+ peer-group INTv6
+ }
+ }
+ }
+ neighbor fd52:d62e:8011:fffe:192:168:253:6 {
+ address-family {
+ ipv6-unicast {
+ peer-group DAL13v6
+ }
+ }
+ }
+ neighbor fd52:d62e:8011:fffe:192:168:253:7 {
+ address-family {
+ ipv6-unicast {
+ peer-group DAL13v6
+ }
+ }
+ }
+ neighbor fd52:d62e:8011:fffe:192:168:253:12 {
+ address-family {
+ ipv6-unicast {
+ route-map {
+ export BGP-BACKBONE-OUT
+ import BGP-BACKBONE-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd {
+ }
+ ebgp-multihop 2
+ remote-as 4242420669
+ update-source dum0
+ }
+ parameters {
+ confederation {
+ identifier 4242420696
+ peers 4242420668
+ peers 4242420669
+ }
+ default {
+ no-ipv4-unicast
+ }
+ distance {
+ global {
+ external 220
+ internal 220
+ local 220
+ }
+ }
+ graceful-restart {
+ }
+ }
+ peer-group DAL13 {
+ address-family {
+ ipv4-unicast {
+ route-map {
+ export BGP-BACKBONE-OUT
+ import BGP-BACKBONE-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd
+ ebgp-multihop 2
+ remote-as 4242420668
+ update-source dum0
+ }
+ peer-group DAL13v6 {
+ address-family {
+ ipv6-unicast {
+ route-map {
+ export BGP-BACKBONE-OUT
+ import BGP-BACKBONE-IN
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd
+ ebgp-multihop 2
+ remote-as 4242420668
+ update-source dum0
+ }
+ peer-group INT {
+ address-family {
+ ipv4-unicast {
+ default-originate {
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd
+ remote-as 4242420666
+ update-source dum0
+ }
+ peer-group INTv6 {
+ address-family {
+ ipv6-unicast {
+ default-originate {
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ bfd
+ remote-as 4242420666
+ update-source dum0
+ }
+ }
+}
+system {
+ config-management {
+ commit-revisions 200
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/
+ plaintext-password ""
+ }
+ level admin
+ }
+ }
+ ntp {
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ }
+ time-zone Europe/Berlin
+}
+
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@10:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
+/* Release version: 1.2.6-S1 */
diff --git a/smoketest/configs/bgp-big-as-cloud b/smoketest/configs/bgp-big-as-cloud
index df3ae015c..694243d1e 100644
--- a/smoketest/configs/bgp-big-as-cloud
+++ b/smoketest/configs/bgp-big-as-cloud
@@ -1186,6 +1186,10 @@ protocols {
}
}
}
+ maximum-paths {
+ ebgp 8
+ ibgp 16
+ }
neighbor 192.0.16.209 {
address-family {
ipv4-unicast {
diff --git a/smoketest/configs/bgp-small-internet-exchange b/smoketest/configs/bgp-small-internet-exchange
index de6213b50..d51f87c4a 100644
--- a/smoketest/configs/bgp-small-internet-exchange
+++ b/smoketest/configs/bgp-small-internet-exchange
@@ -11,6 +11,100 @@ interfaces {
}
}
policy {
+ as-path-list bogon-asns {
+ rule 10 {
+ action permit
+ description "RFC 7607"
+ regex _0_
+ }
+ rule 20 {
+ action permit
+ description "RFC 4893"
+ regex _23456_
+ }
+ rule 30 {
+ action permit
+ description "RFC 5398/6996/7300"
+ regex _6449[6-9]_|_65[0-4][0-9][0-9]_|_655[0-4][0-9]_|_6555[0-1]_
+ }
+ rule 40 {
+ action permit
+ description "IANA reserved"
+ regex _6555[2-9]_|_655[6-9][0-9]_|_65[6-9][0-9][0-9]_|_6[6-9][0-9][0-9][0-]_|_[7-9][0-9][0-9][0-9][0-9]_|_1[0-2][0-9][0-9][0-9][0-9]_|_130[0-9][0-9][0-9]_|_1310[0-6][0-9]_|_13107[01]_
+ }
+ }
+ prefix-list bogon-v4 {
+ rule 10 {
+ action permit
+ le 32
+ prefix 0.0.0.0/8
+ }
+ rule 20 {
+ action permit
+ le 32
+ prefix 10.0.0.0/8
+ }
+ rule 30 {
+ action permit
+ le 32
+ prefix 100.64.0.0/10
+ }
+ rule 40 {
+ action permit
+ le 32
+ prefix 127.0.0.0/8
+ }
+ rule 50 {
+ action permit
+ le 32
+ prefix 169.254.0.0/16
+ }
+ rule 60 {
+ action permit
+ le 32
+ prefix 172.16.0.0/12
+ }
+ rule 70 {
+ action permit
+ le 32
+ prefix 192.0.2.0/24
+ }
+ rule 80 {
+ action permit
+ le 32
+ prefix 192.88.99.0/24
+ }
+ rule 90 {
+ action permit
+ le 32
+ prefix 192.168.0.0/16
+ }
+ rule 100 {
+ action permit
+ le 32
+ prefix 198.18.0.0/15
+ }
+ rule 110 {
+ action permit
+ le 32
+ prefix 198.51.100.0/24
+ }
+ rule 120 {
+ action permit
+ le 32
+ prefix 203.0.113.0/24
+ }
+ rule 130 {
+ action permit
+ le 32
+ prefix 224.0.0.0/4
+ }
+ rule 140 {
+ action permit
+ le 32
+ prefix 240.0.0.0/4
+ }
+ }
prefix-list IX-out-v4 {
rule 10 {
action permit
@@ -21,6 +115,88 @@ policy {
prefix 10.0.128.0/23
}
}
+ prefix-list prefix-filter-v4 {
+ rule 10 {
+ action permit
+ ge 25
+ prefix 0.0.0.0/0
+ }
+ }
+ prefix-list6 bogon-v6 {
+ rule 10 {
+ action permit
+ description "RFC 4291 IPv4-compatible, loopback, et al"
+ le 128
+ prefix ::/8
+ }
+ rule 20 {
+ action permit
+ description "RFC 6666 Discard-Only"
+ le 128
+ prefix 0100::/64
+ }
+ rule 30 {
+ action permit
+ description "RFC 5180 BMWG"
+ le 128
+ prefix 2001:2::/48
+ }
+ rule 40 {
+ action permit
+ description "RFC 4843 ORCHID"
+ le 128
+ prefix 2001:10::/28
+ }
+ rule 50 {
+ action permit
+ description "RFC 3849 documentation"
+ le 128
+ prefix 2001:db8::/32
+ }
+ rule 60 {
+ action permit
+ description "RFC 7526 6to4 anycast relay"
+ le 128
+ prefix 2002::/16
+ }
+ rule 70 {
+ action permit
+ description "RFC 3701 old 6bone"
+ le 128
+ prefix 3ffe::/16
+ }
+ rule 80 {
+ action permit
+ description "RFC 4193 unique local unicast"
+ le 128
+ prefix fc00::/7
+ }
+ rule 90 {
+ action permit
+ description "RFC 4291 link local unicast"
+ le 128
+ prefix fe80::/10
+ }
+ rule 100 {
+ action permit
+ description "RFC 3879 old site local unicast"
+ le 128
+ prefix fec0::/10
+ }
+ rule 110 {
+ action permit
+ description "RFC 4291 multicast"
+ le 128
+ prefix ff00::/8
+ }
+ }
+ prefix-list6 prefix-filter-v6 {
+ rule 10 {
+ action permit
+ ge 49
+ prefix ::/0
+ }
+ }
prefix-list6 IX-out-v6 {
rule 10 {
action permit
@@ -31,6 +207,88 @@ policy {
prefix 2001:db8:200::/40
}
}
+ route-map eBGP-IN-v4 {
+ rule 10 {
+ action deny
+ match {
+ as-path bogon-asns
+ }
+ }
+ rule 20 {
+ action deny
+ match {
+ ip {
+ address {
+ prefix-list bogon-v4
+ }
+ }
+ }
+ }
+ rule 30 {
+ action deny
+ match {
+ ip {
+ address {
+ prefix-list prefix-filter-v4
+ }
+ }
+ }
+ }
+ rule 40 {
+ action permit
+ set {
+ local-preference 100
+ metric 0
+ }
+ }
+ }
+ route-map eBGP-IN-v6 {
+ rule 10 {
+ action deny
+ match {
+ as-path bogon-asns
+ }
+ }
+ rule 20 {
+ action deny
+ match {
+ ipv6 {
+ address {
+ prefix-list bogon-v6
+ }
+ }
+ }
+ }
+ rule 30 {
+ action deny
+ match {
+ ipv6 {
+ address {
+ prefix-list prefix-filter-v6
+ }
+ }
+ }
+ }
+ rule 40 {
+ action permit
+ set {
+ local-preference 100
+ metric 0
+ }
+ }
+ }
+ route-map IX-in-v4 {
+ rule 5 {
+ action permit
+ call eBGP-IN-v4
+ on-match {
+ next
+ }
+ }
+ rule 10 {
+ action permit
+ }
+ }
route-map IX-out-v4 {
rule 10 {
action permit
@@ -43,6 +301,18 @@ policy {
}
}
}
+ route-map IX-in-v6 {
+ rule 5 {
+ action permit
+ call eBGP-IN-v6
+ on-match {
+ next
+ }
+ }
+ rule 10 {
+ action permit
+ }
+ }
route-map IX-out-v6 {
rule 10 {
action permit
diff --git a/smoketest/configs/tunnel-broker b/smoketest/configs/tunnel-broker
new file mode 100644
index 000000000..b52ba2541
--- /dev/null
+++ b/smoketest/configs/tunnel-broker
@@ -0,0 +1,142 @@
+interfaces {
+ dummy dum0 {
+ address 192.0.2.0/32
+ }
+ dummy dum1 {
+ address 192.0.2.1/32
+ }
+ dummy dum2 {
+ address 192.0.2.2/32
+ }
+ dummy dum3 {
+ address 192.0.2.3/32
+ }
+ dummy dum4 {
+ address 192.0.2.4/32
+ }
+ ethernet eth0 {
+ duplex auto
+ smp-affinity auto
+ speed auto
+ address 172.18.202.10/24
+ }
+ l2tpv3 l2tpeth10 {
+ description "L2 VPN Tunnel"
+ destination-port 5010
+ encapsulation ip
+ local-ip 172.18.202.10
+ mtu 1500
+ peer-session-id 110
+ peer-tunnel-id 10
+ remote-ip 172.18.254.201
+ session-id 110
+ source-port 5010
+ tunnel-id 10
+ }
+ l2tpv3 l2tpeth20 {
+ description "L2 VPN Tunnel"
+ destination-port 5020
+ encapsulation ip
+ local-ip 172.18.202.10
+ mtu 1500
+ peer-session-id 120
+ peer-tunnel-id 20
+ remote-ip 172.18.254.202
+ session-id 120
+ source-port 5020
+ tunnel-id 20
+ }
+ l2tpv3 l2tpeth30 {
+ description "L2 VPN Tunnel"
+ destination-port 5030
+ encapsulation ip
+ local-ip 172.18.202.10
+ mtu 1500
+ peer-session-id 130
+ peer-tunnel-id 30
+ remote-ip 172.18.254.203
+ session-id 130
+ source-port 5030
+ tunnel-id 30
+ }
+ tunnel tun100 {
+ address 172.16.0.1/30
+ encapsulation gre-bridge
+ local-ip 192.0.2.0
+ remote-ip 192.0.2.100
+ }
+ tunnel tun200 {
+ address 172.16.0.5/30
+ encapsulation gre
+ local-ip 192.0.2.1
+ remote-ip 192.0.2.101
+ }
+ tunnel tun300 {
+ address 172.16.0.9/30
+ encapsulation ipip
+ local-ip 192.0.2.2
+ remote-ip 192.0.2.102
+ }
+ tunnel tun400 {
+ address 172.16.0.13/30
+ encapsulation gre-bridge
+ local-ip 192.0.2.3
+ remote-ip 192.0.2.103
+ }
+ tunnel tun500 {
+ address 172.16.0.17/30
+ encapsulation gre
+ local-ip 192.0.2.4
+ remote-ip 192.0.2.104
+ }
+}
+protocols {
+ static {
+ route 0.0.0.0/0 {
+ next-hop 172.18.202.1 {
+ distance 10
+ }
+ }
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ ntp {
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ }
+}
+
+/* Warning: Do not remove the following line. */
+/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@10:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */
+/* Release version: 1.2.6-S1 */
diff --git a/smoketest/configs/vrf-bgp b/smoketest/configs/vrf-bgp
new file mode 100644
index 000000000..4ad372a36
--- /dev/null
+++ b/smoketest/configs/vrf-bgp
@@ -0,0 +1,166 @@
+interfaces {
+ ethernet eth0 {
+ address 192.0.2.1/24
+ }
+ ethernet eth1 {
+ vrf black
+ }
+ ethernet eth2 {
+ vrf black
+ }
+}
+protocols {
+ ospf {
+ area 0 {
+ network 192.0.2.0/24
+ }
+ interface eth0 {
+ authentication {
+ md5 {
+ key-id 10 {
+ md5-key ospfkey
+ }
+ }
+ }
+ }
+ log-adjacency-changes {
+ }
+ parameters {
+ abr-type cisco
+ router-id 1.2.3.4
+ }
+ passive-interface default
+ passive-interface-exclude eth0
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ nt
+ ntp {
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ }
+ time-zone Europe/Berlin
+}
+vrf {
+ name black {
+ protocols {
+ bgp 65000 {
+ address-family {
+ ipv4-unicast {
+ network 10.0.150.0/23 {
+ }
+ }
+ ipv6-unicast {
+ network 2001:db8:200::/40 {
+ }
+ }
+ }
+ neighbor 10.0.151.222 {
+ disable-send-community {
+ extended
+ standard
+ }
+ address-family {
+ ipv4-unicast {
+ default-originate {
+ }
+ soft-reconfiguration {
+ inbound
+ }
+ }
+ }
+ capability {
+ dynamic
+ }
+ remote-as 65010
+ }
+ neighbor 10.0.151.252 {
+ peer-group VYOSv4
+ }
+ neighbor 10.0.151.254 {
+ peer-group VYOSv4
+ }
+ neighbor 2001:db8:200:ffff::3 {
+ peer-group VYOSv6
+ }
+ neighbor 2001:db8:200:ffff::a {
+ peer-group VYOSv6
+ }
+ neighbor 2001:db8:200:ff::101:2 {
+ remote-as 65010
+ }
+ parameters {
+ default {
+ no-ipv4-unicast
+ }
+ log-neighbor-changes
+ router-id 10.0.151.251
+ }
+ peer-group VYOSv4 {
+ address-family {
+ ipv4-unicast {
+ nexthop-self {
+ }
+ }
+ }
+ capability {
+ dynamic
+ }
+ remote-as 65000
+ update-source dum0
+ }
+ peer-group VYOSv6 {
+ address-family {
+ ipv6-unicast {
+ nexthop-self {
+ }
+ }
+ }
+ capability {
+ dynamic
+ }
+ remote-as 65000
+ update-source dum0
+ }
+ }
+
+ }
+ table 2000
+ }
+}
+
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@2:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@20:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:nat66@1:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@9:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@20:vrf@2:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
+// Release version: 1.4-rolling-202103130218
diff --git a/smoketest/configs/vrf-ospf b/smoketest/configs/vrf-ospf
new file mode 100644
index 000000000..7855e86bf
--- /dev/null
+++ b/smoketest/configs/vrf-ospf
@@ -0,0 +1,145 @@
+interfaces {
+ ethernet eth0 {
+ address 192.0.2.1/24
+ }
+ ethernet eth1 {
+ vrf red
+ }
+ ethernet eth2 {
+ vrf blue
+ }
+}
+protocols {
+ ospf {
+ area 0 {
+ network 192.0.2.0/24
+ }
+ interface eth0 {
+ authentication {
+ md5 {
+ key-id 10 {
+ md5-key ospfkey
+ }
+ }
+ }
+ }
+ log-adjacency-changes {
+ }
+ parameters {
+ abr-type cisco
+ router-id 1.2.3.4
+ }
+ passive-interface default
+ passive-interface-exclude eth0
+ }
+}
+system {
+ config-management {
+ commit-revisions 100
+ }
+ console {
+ device ttyS0 {
+ speed 115200
+ }
+ }
+ host-name vyos
+ login {
+ user vyos {
+ authentication {
+ encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0
+ plaintext-password ""
+ }
+ }
+ }
+ nt
+ ntp {
+ server 0.pool.ntp.org {
+ }
+ server 1.pool.ntp.org {
+ }
+ server 2.pool.ntp.org {
+ }
+ }
+ syslog {
+ global {
+ facility all {
+ level info
+ }
+ facility protocols {
+ level debug
+ }
+ }
+ }
+ time-zone Europe/Berlin
+}
+vrf {
+ name blue {
+ protocols {
+ ospf {
+ area 0 {
+ network 172.18.201.0/24
+ }
+ interface eth2 {
+ authentication {
+ md5 {
+ key-id 30 {
+ md5-key vyoskey456
+ }
+ }
+ }
+ dead-interval 40
+ hello-interval 10
+ priority 1
+ retransmit-interval 5
+ transmit-delay 1
+ }
+ log-adjacency-changes {
+ }
+ parameters {
+ abr-type cisco
+ router-id 5.6.7.8
+ }
+ passive-interface default
+ passive-interface-exclude eth2
+ }
+ }
+ table 2000
+ }
+ name red {
+ protocols {
+ ospf {
+ area 0 {
+ network 172.18.202.0/24
+ }
+ interface eth1 {
+ authentication {
+ md5 {
+ key-id 20 {
+ md5-key vyoskey123
+ }
+ }
+ }
+ dead-interval 40
+ hello-interval 10
+ priority 1
+ retransmit-interval 5
+ transmit-delay 1
+ }
+ log-adjacency-changes {
+ }
+ parameters {
+ abr-type cisco
+ router-id 9.10.11.12
+ }
+ passive-interface default
+ passive-interface-exclude eth1
+ }
+ }
+ table 1000
+ }
+}
+
+
+// Warning: Do not remove the following line.
+// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@2:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@20:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:nat66@1:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@9:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@20:vrf@2:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
+// Release version: 1.4-rolling-202103130218
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 1426e80c2..50cfa2607 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -14,7 +14,6 @@
import os
import unittest
-import json
from binascii import hexlify
@@ -30,6 +29,7 @@ from vyos.util import read_file
from vyos.util import cmd
from vyos.util import dict_search
from vyos.util import process_named_running
+from vyos.util import get_interface_config
from vyos.validate import is_intf_addr_assigned
from vyos.validate import is_ipv6_link_local
@@ -292,6 +292,42 @@ class BasicInterfaceTest:
self.assertEqual(tmp, self._mtu)
self.assertEqual(Interface(vif).get_admin_state(), 'up')
+ def test_vif_8021q_lower_up_down(self):
+ # Testcase for https://phabricator.vyos.net/T3349
+ if not self._test_vlan:
+ self.skipTest('not supported')
+
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ for option in self._options.get(interface, []):
+ self.session.set(base + option.split())
+
+ # disable the lower interface
+ self.session.set(base + ['disable'])
+
+ for vlan in self._vlan_range:
+ vlan_base = self._base_path + [interface, 'vif', vlan]
+ # disable the vlan interface
+ self.session.set(vlan_base + ['disable'])
+
+ self.session.commit()
+
+ # re-enable all lower interfaces
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.session.delete(base + ['disable'])
+
+ self.session.commit()
+
+ # verify that the lower interfaces are admin up and the vlan
+ # interfaces are all admin down
+ for interface in self._interfaces:
+ self.assertEqual(Interface(interface).get_admin_state(), 'up')
+
+ for vlan in self._vlan_range:
+ ifname = f'{interface}.{vlan}'
+ self.assertEqual(Interface(ifname).get_admin_state(), 'down')
+
def test_vif_s_8021ad_vlan_interfaces(self):
# XXX: This testcase is not allowed to run as first testcase, reason
@@ -317,7 +353,7 @@ class BasicInterfaceTest:
for interface in self._interfaces:
for vif_s in self._qinq_range:
- tmp = json.loads(cmd(f'ip -d -j link show dev {interface}.{vif_s}'))[0]
+ tmp = get_interface_config(f'{interface}.{vif_s}')
self.assertEqual(dict_search('linkinfo.info_data.protocol', tmp), '802.1ad')
for vif_c in self._vlan_range:
diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py
index f64b527b3..7e10f12c4 100755
--- a/smoketest/scripts/cli/test_interfaces_bridge.py
+++ b/smoketest/scripts/cli/test_interfaces_bridge.py
@@ -99,6 +99,12 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest):
self.session.set(base + ['enable-vlan'])
super().test_vif_8021q_interfaces()
+ def test_vif_8021q_lower_up_down(self):
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.session.set(base + ['enable-vlan'])
+ super().test_vif_8021q_interfaces()
+
def test_bridge_vlan_filter(self):
vif_vlan = 2
diff --git a/smoketest/scripts/cli/test_interfaces_erspan.py b/smoketest/scripts/cli/test_interfaces_erspan.py
index c180f0a34..4575c61ce 100755
--- a/smoketest/scripts/cli/test_interfaces_erspan.py
+++ b/smoketest/scripts/cli/test_interfaces_erspan.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
@@ -15,65 +15,15 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
-import json
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
-from vyos.util import cmd
+from vyos.util import get_interface_config
from base_interfaces_test import BasicInterfaceTest
mtu = 1500
-def erspan_conf(interface):
- tmp = cmd(f'ip -d -j link show {interface}')
- '''
- [
- {
- "ifindex": 17,
- "link": null,
- "ifname": "ersp0",
- "flags": [
- "BROADCAST",
- "MULTICAST"
- ],
- "mtu": 1450,
- "qdisc": "noop",
- "operstate": "DOWN",
- "linkmode": "DEFAULT",
- "group": "default",
- "txqlen": 1000,
- "link_type": "ether",
- "address": "22:27:14:7b:0d:79",
- "broadcast": "ff:ff:ff:ff:ff:ff",
- "promiscuity": 0,
- "min_mtu": 68,
- "max_mtu": 0,
- "linkinfo": {
- "info_kind": "erspan",
- "info_data": {
- "remote": "10.2.2.2",
- "local": "10.1.1.1",
- "ttl": 0,
- "pmtudisc": true,
- "ikey": "0.0.0.123",
- "okey": "0.0.0.123",
- "iseq": true,
- "oseq": true,
- "erspan_index": 0,
- "erspan_ver": 1
- }
- },
- "inet6_addr_gen_mode": "eui64",
- "num_tx_queues": 1,
- "num_rx_queues": 1,
- "gso_max_size": 65536,
- "gso_max_segs": 65535
- }
- ]
- '''
- return json.loads(tmp)[0]
-
class ERSPanTunnelInterfaceTest(BasicInterfaceTest.BaseTest):
def setUp(self):
super().setUp()
@@ -96,19 +46,19 @@ class ERSPanTunnelInterfaceTest(BasicInterfaceTest.BaseTest):
key = 123
self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
- self.session.set(self._base_path + [interface, 'remote-ip', self.remote_v4])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote', self.remote_v4])
self.session.set(self._base_path + [interface, 'parameters', 'ip' , 'key', str(key)])
self.session.commit()
- conf = erspan_conf(interface)
+ conf = get_interface_config(interface)
self.assertEqual(interface, conf['ifname'])
self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
self.assertEqual(mtu, conf['mtu'])
- self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
- self.assertEqual(self.remote_v4, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(self.remote_v4, conf['linkinfo']['info_data']['remote'])
def test_erspan_ipv6(self):
@@ -117,19 +67,19 @@ class ERSPanTunnelInterfaceTest(BasicInterfaceTest.BaseTest):
key = 123
self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v6])
- self.session.set(self._base_path + [interface, 'remote-ip', self.remote_v6])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v6])
+ self.session.set(self._base_path + [interface, 'remote', self.remote_v6])
self.session.set(self._base_path + [interface, 'parameters', 'ip' , 'key', str(key)])
self.session.commit()
- conf = erspan_conf(interface)
+ conf = get_interface_config(interface)
self.assertEqual(interface, conf['ifname'])
self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
self.assertEqual(mtu, conf['mtu'])
- self.assertEqual(self.local_v6, conf['linkinfo']['info_data']['local'])
- self.assertEqual(self.remote_v6, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(self.local_v6, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(self.remote_v6, conf['linkinfo']['info_data']['remote'])
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_geneve.py b/smoketest/scripts/cli/test_interfaces_geneve.py
index b708b5437..e8e8e5a2c 100755
--- a/smoketest/scripts/cli/test_interfaces_geneve.py
+++ b/smoketest/scripts/cli/test_interfaces_geneve.py
@@ -17,6 +17,9 @@
import unittest
from vyos.configsession import ConfigSession
+from vyos.ifconfig import Interface
+from vyos.util import get_interface_config
+
from base_interfaces_test import BasicInterfaceTest
class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
@@ -28,8 +31,49 @@ class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
cls._options = {
'gnv0': ['vni 10', 'remote 127.0.1.1'],
'gnv1': ['vni 20', 'remote 127.0.1.2'],
+ 'gnv1': ['vni 30', 'remote 2001:db8::1', 'parameters ipv6 flowlabel 0x1000'],
}
cls._interfaces = list(cls._options)
+ def test_geneve_parameters(self):
+ tos = '40'
+ ttl = 20
+ for intf in self._interfaces:
+ for option in self._options.get(intf, []):
+ self.session.set(self._base_path + [intf] + option.split())
+
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'dont-fragment'])
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'tos', tos])
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'ttl', str(ttl)])
+ ttl += 10
+
+ self.session.commit()
+
+ ttl = 20
+ for interface in self._interfaces:
+ options = get_interface_config(interface)
+
+ vni = options['linkinfo']['info_data']['id']
+ self.assertIn(f'vni {vni}', self._options[interface])
+
+ if any('remote' in s for s in self._options[interface]):
+ key = 'remote'
+ if 'remote6' in options['linkinfo']['info_data']:
+ key = 'remote6'
+
+ remote = options['linkinfo']['info_data'][key]
+ self.assertIn(f'remote {remote}', self._options[interface])
+
+ if any('flowlabel' in s for s in self._options[interface]):
+ label = options['linkinfo']['info_data']['label']
+ self.assertIn(f'parameters ipv6 flowlabel {label}', self._options[interface])
+
+ self.assertEqual('geneve', options['linkinfo']['info_kind'])
+ self.assertEqual('set', options['linkinfo']['info_data']['df'])
+ self.assertEqual(f'0x{tos}', options['linkinfo']['info_data']['tos'])
+ self.assertEqual(ttl, options['linkinfo']['info_data']['ttl'])
+ self.assertEqual(Interface(interface).get_admin_state(), 'up')
+ ttl += 10
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_interfaces_l2tpv3.py b/smoketest/scripts/cli/test_interfaces_l2tpv3.py
index a89895b92..74fd4f6c6 100755
--- a/smoketest/scripts/cli/test_interfaces_l2tpv3.py
+++ b/smoketest/scripts/cli/test_interfaces_l2tpv3.py
@@ -27,12 +27,12 @@ class GeneveInterfaceTest(BasicInterfaceTest.BaseTest):
cls._test_ipv6 = True
cls._base_path = ['interfaces', 'l2tpv3']
cls._options = {
- 'l2tpeth10': ['local-ip 127.0.0.1', 'remote-ip 127.10.10.10',
+ 'l2tpeth10': ['source-address 127.0.0.1', 'remote 127.10.10.10',
'tunnel-id 100', 'peer-tunnel-id 10',
'session-id 100', 'peer-session-id 10',
'source-port 1010', 'destination-port 10101'],
- 'l2tpeth20': ['local-ip 127.0.0.1', 'peer-session-id 20',
- 'peer-tunnel-id 200', 'remote-ip 127.20.20.20',
+ 'l2tpeth20': ['source-address 127.0.0.1', 'peer-session-id 20',
+ 'peer-tunnel-id 200', 'remote 127.20.20.20',
'session-id 20', 'tunnel-id 200',
'source-port 2020', 'destination-port 20202'],
}
diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py
index 3a3e7bff3..31071a0f7 100755
--- a/smoketest/scripts/cli/test_interfaces_macsec.py
+++ b/smoketest/scripts/cli/test_interfaces_macsec.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import os
import re
import unittest
@@ -22,7 +23,9 @@ from netifaces import interfaces
from vyos.configsession import ConfigSessionError
from vyos.ifconfig import Section
+from vyos.util import cmd
from vyos.util import read_file
+from vyos.util import get_interface_config
from vyos.util import process_named_running
def get_config_value(interface, key):
@@ -30,6 +33,10 @@ def get_config_value(interface, key):
tmp = re.findall(r'\n?{}=(.*)'.format(key), tmp)
return tmp[0]
+def get_cipher(interface):
+ tmp = get_interface_config(interface)
+ return tmp['linkinfo']['info_data']['cipher_suite'].lower()
+
class MACsecInterfaceTest(BasicInterfaceTest.BaseTest):
@classmethod
def setUpClass(cls):
@@ -107,8 +114,30 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest):
# Check for running process
self.assertTrue(process_named_running('wpa_supplicant'))
- def test_macsec_mandatory_options(self):
+ def test_macsec_gcm_aes_128(self):
interface = 'macsec1'
+ cipher = 'gcm-aes-128'
+ self.session.set(self._base_path + [interface])
+
+ # check validate() - source interface is mandatory
+ with self.assertRaises(ConfigSessionError):
+ self.session.commit()
+ self.session.set(self._base_path + [interface, 'source-interface', 'eth0'])
+
+ # check validate() - cipher is mandatory
+ with self.assertRaises(ConfigSessionError):
+ self.session.commit()
+ self.session.set(self._base_path + [interface, 'security', 'cipher', cipher])
+
+ # final commit and verify
+ self.session.commit()
+ self.assertIn(interface, interfaces())
+ self.assertIn(interface, interfaces())
+ self.assertEqual(cipher, get_cipher(interface))
+
+ def test_macsec_gcm_aes_256(self):
+ interface = 'macsec4'
+ cipher = 'gcm-aes-256'
self.session.set(self._base_path + [interface])
# check validate() - source interface is mandatory
@@ -119,11 +148,12 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest):
# check validate() - cipher is mandatory
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(self._base_path + [interface, 'security', 'cipher', 'gcm-aes-128'])
+ self.session.set(self._base_path + [interface, 'security', 'cipher', cipher])
# final commit and verify
self.session.commit()
self.assertIn(interface, interfaces())
+ self.assertEqual(cipher, get_cipher(interface))
def test_macsec_source_interface(self):
# Ensure source-interface can bot be part of any other bond or bridge
diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py
index a9250e3e5..3dddb5ef0 100755
--- a/smoketest/scripts/cli/test_interfaces_tunnel.py
+++ b/smoketest/scripts/cli/test_interfaces_tunnel.py
@@ -15,11 +15,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
-import json
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
-from vyos.util import cmd
+from vyos.util import get_interface_config
+from vyos.template import inc_ip
from base_interfaces_test import BasicInterfaceTest
@@ -28,38 +28,6 @@ remote_ip6 = '2001:db8::ffff'
source_if = 'dum2222'
mtu = 1476
-def tunnel_conf(interface):
- tmp = cmd(f'ip -d -j link show {interface}')
- # {'address': '2.2.2.2',
- # 'broadcast': '192.0.2.10',
- # 'flags': ['POINTOPOINT', 'NOARP', 'UP', 'LOWER_UP'],
- # 'group': 'default',
- # 'gso_max_segs': 65535,
- # 'gso_max_size': 65536,
- # 'ifindex': 10,
- # 'ifname': 'tun10',
- # 'inet6_addr_gen_mode': 'none',
- # 'link': None,
- # 'link_pointtopoint': True,
- # 'link_type': 'gre',
- # 'linkinfo': {'info_data': {'local': '2.2.2.2',
- # 'pmtudisc': True,
- # 'remote': '192.0.2.10',
- # 'tos': '0x1',
- # 'ttl': 255},
- # 'info_kind': 'gre'},
- # 'linkmode': 'DEFAULT',
- # 'max_mtu': 65511,
- # 'min_mtu': 68,
- # 'mtu': 1476,
- # 'num_rx_queues': 1,
- # 'num_tx_queues': 1,
- # 'operstate': 'UNKNOWN',
- # 'promiscuity': 0,
- # 'qdisc': 'noqueue',
- # 'txqlen': 1000}
- return json.loads(tmp)[0]
-
class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
@classmethod
def setUpClass(cls):
@@ -70,8 +38,8 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
cls.local_v4 = '192.0.2.1'
cls.local_v6 = '2001:db8::1'
cls._options = {
- 'tun10': ['encapsulation ipip', 'remote-ip 192.0.2.10', 'local-ip ' + cls.local_v4],
- 'tun20': ['encapsulation gre', 'remote-ip 192.0.2.20', 'local-ip ' + cls.local_v4],
+ 'tun10': ['encapsulation ipip', 'remote 192.0.2.10', 'source-address ' + cls.local_v4],
+ 'tun20': ['encapsulation gre', 'remote 192.0.2.20', 'source-address ' + cls.local_v4],
}
cls._interfaces = list(cls._options)
@@ -90,25 +58,25 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
interface = f'tun1000'
local_if_addr = f'10.10.200.1/24'
- for encapsulation in ['ipip', 'sit', 'gre', 'gre-bridge']:
+ for encapsulation in ['ipip', 'sit', 'gre', 'gretap']:
self.session.set(self._base_path + [interface, 'address', local_if_addr])
self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v6])
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip6])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v6])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip6])
- # Encapsulation mode requires IPv4 local-ip
+ # Encapsulation mode requires IPv4 source-address
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
- # Encapsulation mode requires IPv4 local-ip
+ # Encapsulation mode requires IPv4 remote
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip4])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip4])
self.session.set(self._base_path + [interface, 'source-interface', source_if])
- # Source interface can not be used with sit and gre-bridge
- if encapsulation in ['sit', 'gre-bridge']:
+ # Source interface can not be used with sit and gretap
+ if encapsulation in ['sit', 'gretap']:
with self.assertRaises(ConfigSessionError):
self.session.commit()
self.session.delete(self._base_path + [interface, 'source-interface'])
@@ -116,18 +84,15 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
# Check if commit is ok
self.session.commit()
- conf = tunnel_conf(interface)
- self.assertEqual(interface, conf['ifname'])
- self.assertEqual(mtu, conf['mtu'])
-
- if encapsulation not in ['sit', 'gre-bridge']:
+ conf = get_interface_config(interface)
+ if encapsulation not in ['sit', 'gretap']:
self.assertEqual(source_if, conf['link'])
- self.assertEqual(encapsulation, conf['link_type'])
- elif encapsulation in ['gre-bridge']:
- self.assertEqual('ether', conf['link_type'])
+ self.assertEqual(interface, conf['ifname'])
+ self.assertEqual(mtu, conf['mtu'])
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
- self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
self.assertTrue(conf['linkinfo']['info_data']['pmtudisc'])
# cleanup this instance
@@ -140,41 +105,49 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
interface = f'tun1010'
local_if_addr = f'10.10.200.1/24'
- for encapsulation in ['ipip6', 'ip6ip6', 'ip6gre']:
+ for encapsulation in ['ipip6', 'ip6ip6', 'ip6gre', 'ip6gretap']:
self.session.set(self._base_path + [interface, 'address', local_if_addr])
self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip4])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip4])
- # Encapsulation mode requires IPv6 local-ip
+ # Encapsulation mode requires IPv6 source-address
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v6])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v6])
- # Encapsulation mode requires IPv6 local-ip
+ # Encapsulation mode requires IPv6 remote
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip6])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip6])
# Configure Tunnel Source interface
self.session.set(self._base_path + [interface, 'source-interface', source_if])
+ # Source interface can not be used with ip6gretap
+ if encapsulation in ['ip6gretap']:
+ with self.assertRaises(ConfigSessionError):
+ self.session.commit()
+ self.session.delete(self._base_path + [interface, 'source-interface'])
# Check if commit is ok
self.session.commit()
- conf = tunnel_conf(interface)
+ conf = get_interface_config(interface)
+ if encapsulation not in ['ip6gretap']:
+ self.assertEqual(source_if, conf['link'])
+
self.assertEqual(interface, conf['ifname'])
self.assertEqual(mtu, conf['mtu'])
- self.assertEqual(source_if, conf['link'])
- # remap encapsulation protocol(s)
- if encapsulation in ['ipip6', 'ip6ip6']:
- encapsulation = 'tunnel6'
- elif encapsulation in ['ip6gre']:
- encapsulation = 'gre6'
+ # Not applicable for ip6gre
+ if 'proto' in conf['linkinfo']['info_data']:
+ self.assertEqual(encapsulation, conf['linkinfo']['info_data']['proto'])
- self.assertEqual(encapsulation, conf['link_type'])
+ # remap encapsulation protocol(s) only for ipip6, ip6ip6
+ if encapsulation in ['ipip6', 'ip6ip6']:
+ encapsulation = 'ip6tnl'
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
self.assertEqual(self.local_v6, conf['linkinfo']['info_data']['local'])
self.assertEqual(remote_ip6, conf['linkinfo']['info_data']['remote'])
@@ -183,18 +156,18 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
self.session.commit()
def test_tunnel_verify_local_dhcp(self):
- # We can not use local-ip and dhcp-interface at the same time
+ # We can not use source-address and dhcp-interface at the same time
interface = f'tun1020'
local_if_addr = f'10.0.0.1/24'
self.session.set(self._base_path + [interface, 'address', local_if_addr])
self.session.set(self._base_path + [interface, 'encapsulation', 'gre'])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip4])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip4])
self.session.set(self._base_path + [interface, 'dhcp-interface', 'eth0'])
- # local-ip and dhcp-interface can not be used at the same time
+ # source-address and dhcp-interface can not be used at the same time
with self.assertRaises(ConfigSessionError):
self.session.commit()
self.session.delete(self._base_path + [interface, 'dhcp-interface'])
@@ -209,8 +182,8 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
tos = '20'
self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
- self.session.set(self._base_path + [interface, 'local-ip', self.local_v4])
- self.session.set(self._base_path + [interface, 'remote-ip', remote_ip4])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip4])
self.session.set(self._base_path + [interface, 'parameters', 'ip', 'no-pmtu-discovery'])
self.session.set(self._base_path + [interface, 'parameters', 'ip', 'key', gre_key])
@@ -219,14 +192,44 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest):
# Check if commit is ok
self.session.commit()
- conf = tunnel_conf(interface)
+ conf = get_interface_config(interface)
self.assertEqual(mtu, conf['mtu'])
self.assertEqual(interface, conf['ifname'])
- self.assertEqual(encapsulation, conf['link_type'])
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
self.assertEqual(0, conf['linkinfo']['info_data']['ttl'])
self.assertFalse( conf['linkinfo']['info_data']['pmtudisc'])
+ def test_gretap_parameters_change(self):
+ interface = f'tun1040'
+ gre_key = '10'
+ encapsulation = 'gretap'
+ tos = '20'
+
+ self.session.set(self._base_path + [interface, 'encapsulation', encapsulation])
+ self.session.set(self._base_path + [interface, 'source-address', self.local_v4])
+ self.session.set(self._base_path + [interface, 'remote', remote_ip4])
+
+ # Check if commit is ok
+ self.session.commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(mtu, conf['mtu'])
+ self.assertEqual(interface, conf['ifname'])
+ self.assertEqual(encapsulation, conf['linkinfo']['info_kind'])
+ self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local'])
+ self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote'])
+ self.assertEqual(0, conf['linkinfo']['info_data']['ttl'])
+
+ # Change remote ip address (inc host by 2
+ new_remote = inc_ip(remote_ip4, 2)
+ self.session.set(self._base_path + [interface, 'remote', new_remote])
+ # Check if commit is ok
+ self.session.commit()
+
+ conf = get_interface_config(interface)
+ self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote'])
+
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py
index fcc1b15ce..2a04b0477 100755
--- a/smoketest/scripts/cli/test_interfaces_vxlan.py
+++ b/smoketest/scripts/cli/test_interfaces_vxlan.py
@@ -16,7 +16,10 @@
import unittest
-from vyos.configsession import ConfigSession, ConfigSessionError
+from vyos.configsession import ConfigSession
+from vyos.ifconfig import Interface
+from vyos.util import get_interface_config
+
from base_interfaces_test import BasicInterfaceTest
class VXLANInterfaceTest(BasicInterfaceTest.BaseTest):
@@ -27,10 +30,59 @@ class VXLANInterfaceTest(BasicInterfaceTest.BaseTest):
cls._test_mtu = True
cls._base_path = ['interfaces', 'vxlan']
cls._options = {
- 'vxlan0': ['vni 10', 'remote 127.0.0.2'],
- 'vxlan1': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'],
+ 'vxlan10': ['vni 10', 'remote 127.0.0.2'],
+ 'vxlan20': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'],
+ 'vxlan30': ['vni 30', 'remote 2001:db8:2000::1', 'source-address 2001:db8:1000::1', 'parameters ipv6 flowlabel 0x1000'],
}
cls._interfaces = list(cls._options)
+ def test_vxlan_parameters(self):
+ tos = '40'
+ ttl = 20
+ for intf in self._interfaces:
+ for option in self._options.get(intf, []):
+ self.session.set(self._base_path + [intf] + option.split())
+
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'dont-fragment'])
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'tos', tos])
+ self.session.set(self._base_path + [intf, 'parameters', 'ip', 'ttl', str(ttl)])
+ ttl += 10
+
+ self.session.commit()
+
+ ttl = 20
+ for interface in self._interfaces:
+ options = get_interface_config(interface)
+
+ vni = options['linkinfo']['info_data']['id']
+ self.assertIn(f'vni {vni}', self._options[interface])
+
+ if any('link' in s for s in self._options[interface]):
+ link = options['linkinfo']['info_data']['link']
+ self.assertIn(f'source-interface {link}', self._options[interface])
+
+ if any('local6' in s for s in self._options[interface]):
+ remote = options['linkinfo']['info_data']['local6']
+ self.assertIn(f'source-address {local6}', self._options[interface])
+
+ if any('remote6' in s for s in self._options[interface]):
+ remote = options['linkinfo']['info_data']['remote6']
+ self.assertIn(f'remote {remote}', self._options[interface])
+
+ if any('group' in s for s in self._options[interface]):
+ group = options['linkinfo']['info_data']['group']
+ self.assertIn(f'group {group}', self._options[interface])
+
+ if any('flowlabel' in s for s in self._options[interface]):
+ label = options['linkinfo']['info_data']['label']
+ self.assertIn(f'parameters ipv6 flowlabel {label}', self._options[interface])
+
+ self.assertEqual('vxlan', options['linkinfo']['info_kind'])
+ self.assertEqual('set', options['linkinfo']['info_data']['df'])
+ self.assertEqual(f'0x{tos}', options['linkinfo']['info_data']['tos'])
+ self.assertEqual(ttl, options['linkinfo']['info_data']['ttl'])
+ self.assertEqual(Interface(interface).get_admin_state(), 'up')
+ ttl += 10
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py
index ccc4196e0..4838fb8d8 100755
--- a/smoketest/scripts/cli/test_nat66.py
+++ b/smoketest/scripts/cli/test_nat66.py
@@ -44,7 +44,7 @@ class TestNAT66(unittest.TestCase):
translation_prefix = 'fc01::/64'
self.session.set(src_path + ['rule', '1', 'outbound-interface', 'eth1'])
self.session.set(src_path + ['rule', '1', 'source', 'prefix', source_prefix])
- self.session.set(src_path + ['rule', '1', 'translation', 'prefix', translation_prefix])
+ self.session.set(src_path + ['rule', '1', 'translation', 'address', translation_prefix])
# check validate() - outbound-interface must be defined
self.session.commit()
@@ -70,6 +70,36 @@ class TestNAT66(unittest.TestCase):
self.assertEqual(f'{translation_address}/{translation_mask}', translation_prefix)
self.assertEqual(f'{address}/{mask}', source_prefix)
+ def test_source_nat66_address(self):
+ source_prefix = 'fc00::/64'
+ translation_address = 'fc00::1'
+ self.session.set(src_path + ['rule', '1', 'outbound-interface', 'eth1'])
+ self.session.set(src_path + ['rule', '1', 'source', 'prefix', source_prefix])
+ self.session.set(src_path + ['rule', '1', 'translation', 'address', translation_address])
+
+ # check validate() - outbound-interface must be defined
+ self.session.commit()
+
+ tmp = cmd('sudo nft -j list table ip6 nat')
+ data_json = jmespath.search('nftables[?rule].rule[?chain]', json.loads(tmp))
+
+ for idx in range(0, len(data_json)):
+ data = data_json[idx]
+
+ self.assertEqual(data['chain'], 'POSTROUTING')
+ self.assertEqual(data['family'], 'ip6')
+ self.assertEqual(data['table'], 'nat')
+
+ iface = dict_search('match.right', data['expr'][0])
+ address = dict_search('match.right.prefix.addr', data['expr'][2])
+ mask = dict_search('match.right.prefix.len', data['expr'][2])
+ snat_address = dict_search('snat.addr', data['expr'][3])
+
+ self.assertEqual(iface, 'eth1')
+ # check for translation address
+ self.assertEqual(snat_address, translation_address)
+ self.assertEqual(f'{address}/{mask}', source_prefix)
+
def test_destination_nat66(self):
destination_address = 'fc00::1'
translation_address = 'fc01::1'
@@ -127,7 +157,6 @@ class TestNAT66(unittest.TestCase):
# T2813: Ensure translation address is specified
rule = '5'
source_prefix = 'fc00::/64'
- translation_prefix = 'fc00:2::/64'
self.session.set(src_path + ['rule', rule, 'source', 'prefix', source_prefix])
# check validate() - outbound-interface must be defined
@@ -139,7 +168,7 @@ class TestNAT66(unittest.TestCase):
with self.assertRaises(ConfigSessionError):
self.session.commit()
- self.session.set(src_path + ['rule', rule, 'translation', 'prefix', translation_prefix])
+ self.session.set(src_path + ['rule', rule, 'translation', 'address', 'masquerade'])
self.session.commit()
def test_nat66_no_rules(self):
diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py
new file mode 100755
index 000000000..8efbab7e5
--- /dev/null
+++ b/smoketest/scripts/cli/test_policy.py
@@ -0,0 +1,681 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import unittest
+
+from vyos.util import cmd
+from vyos.configsession import ConfigSession
+from vyos.configsession import ConfigSessionError
+
+base_path = ['policy']
+
+def getFRRconfig(section):
+ return cmd(f'vtysh -c "show run" | sed -n "/^{section}/,/^!/p"')
+
+class TestPolicy(unittest.TestCase):
+ def setUp(self):
+ self.session = ConfigSession(os.getpid())
+
+ def tearDown(self):
+ self.session.delete(base_path)
+ self.session.commit()
+ del self.session
+
+ def test_access_list(self):
+ acls = {
+ '50' : {
+ 'rule' : {
+ '5' : {
+ 'action' : 'permit',
+ 'source' : { 'any' : '' },
+ },
+ '10' : {
+ 'action' : 'deny',
+ 'source' : { 'host' : '1.2.3.4' },
+ },
+ },
+ },
+ '150' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'source' : { 'any' : '' },
+ 'destination' : { 'host' : '2.2.2.2' },
+ },
+ '10' : {
+ 'action' : 'deny',
+ 'source' : { 'any' : '' },
+ 'destination' : { 'any' : '' },
+ },
+ },
+ },
+ '2000' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'destination' : { 'any' : '' },
+ 'source' : { 'network' : '10.0.0.0', 'inverse-mask' : '0.255.255.255' },
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'destination' : { 'any' : '' },
+ 'source' : { 'network' : '172.16.0.0', 'inverse-mask' : '0.15.255.255' },
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'destination' : { 'any' : '' },
+ 'source' : { 'network' : '192.168.0.0', 'inverse-mask' : '0.0.255.255' },
+ },
+ '50' : {
+ 'action' : 'permit',
+ 'destination' : { 'network' : '172.16.0.0', 'inverse-mask' : '0.15.255.255' },
+ 'source' : { 'network' : '10.0.0.0', 'inverse-mask' : '0.255.255.255' },
+ },
+ '60' : {
+ 'action' : 'deny',
+ 'destination' : { 'network' : '192.168.0.0', 'inverse-mask' : '0.0.255.255' },
+ 'source' : { 'network' : '172.16.0.0', 'inverse-mask' : '0.15.255.255' },
+ },
+ '70' : {
+ 'action' : 'deny',
+ 'destination' : { 'any' : '' },
+ 'source' : { 'any' : '' },
+ },
+ },
+ },
+ }
+
+ for acl, acl_config in acls.items():
+ path = base_path + ['access-list', acl]
+ self.session.set(path + ['description', f'VyOS-ACL-{acl}'])
+ if 'rule' not in acl_config:
+ continue
+
+ for rule, rule_config in acl_config['rule'].items():
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ for direction in ['source', 'destination']:
+ if direction in rule_config:
+ if 'any' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'any'])
+ if 'host' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'host', rule_config[direction]['host']])
+ if 'network' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'network', rule_config[direction]['network']])
+ self.session.set(path + ['rule', rule, direction, 'inverse-mask', rule_config[direction]['inverse-mask']])
+
+ self.session.commit()
+
+ config = getFRRconfig('access-list')
+ for acl, acl_config in acls.items():
+ seq = '5'
+ for rule, rule_config in acl_config['rule'].items():
+ tmp = f'access-list {acl} seq {seq}'
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ if {'source', 'destination'} <= set(rule_config):
+ tmp += ' ip'
+
+ for direction in ['source', 'destination']:
+ if direction in rule_config:
+ if 'any' in rule_config[direction]:
+ tmp += ' any'
+ if 'host' in rule_config[direction]:
+ tmp += ' ' + rule_config[direction]['host']
+ if 'network' in rule_config[direction]:
+ tmp += ' ' + rule_config[direction]['network'] + ' ' + rule_config[direction]['inverse-mask']
+
+ self.assertIn(tmp, config)
+ seq = int(seq) + 5
+
+ def test_access_list6(self):
+ acls = {
+ '50' : {
+ 'rule' : {
+ '5' : {
+ 'action' : 'permit',
+ 'source' : { 'any' : '' },
+ },
+ '10' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:10::/48', 'exact-match' : '' },
+ },
+ '10' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:20::/48' },
+ },
+ },
+ },
+ '100' : {
+ 'rule' : {
+ '5' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:10::/64', 'exact-match' : '' },
+ },
+ '10' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:20::/64', },
+ },
+ '15' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:30::/64', 'exact-match' : '' },
+ },
+ '20' : {
+ 'action' : 'deny',
+ 'source' : { 'network' : '2001:db8:40::/64', 'exact-match' : '' },
+ },
+ '100' : {
+ 'action' : 'deny',
+ 'source' : { 'any' : '' },
+ },
+ },
+ },
+ }
+
+ for acl, acl_config in acls.items():
+ path = base_path + ['access-list6', acl]
+ self.session.set(path + ['description', f'VyOS-ACL-{acl}'])
+ if 'rule' not in acl_config:
+ continue
+
+ for rule, rule_config in acl_config['rule'].items():
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ for direction in ['source', 'destination']:
+ if direction in rule_config:
+ if 'any' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'any'])
+ if 'network' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'network', rule_config[direction]['network']])
+ if 'exact-match' in rule_config[direction]:
+ self.session.set(path + ['rule', rule, direction, 'exact-match'])
+
+ self.session.commit()
+
+ config = getFRRconfig('ipv6 access-list')
+ for acl, acl_config in acls.items():
+ seq = '5'
+ for rule, rule_config in acl_config['rule'].items():
+ tmp = f'ipv6 access-list {acl} seq {seq}'
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ if {'source', 'destination'} <= set(rule_config):
+ tmp += ' ip'
+
+ for direction in ['source', 'destination']:
+ if direction in rule_config:
+ if 'any' in rule_config[direction]:
+ tmp += ' any'
+ if 'network' in rule_config[direction]:
+ tmp += ' ' + rule_config[direction]['network']
+ if 'exact-match' in rule_config[direction]:
+ tmp += ' exact-match'
+
+ self.assertIn(tmp, config)
+ seq = int(seq) + 5
+
+
+ def test_as_path_list(self):
+ test_data = {
+ 'VyOS' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'regex' : '^44501 64502$',
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'regex' : '44501|44502|44503',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'regex' : '^44501_([0-9]+_)+',
+ },
+ },
+ },
+ 'Customers' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'regex' : '_10_',
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'regex' : '_20_',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'regex' : '_30_',
+ },
+ '30' : {
+ 'action' : 'deny',
+ 'regex' : '_40_',
+ },
+ },
+ },
+ 'bogons' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'regex' : '_0_',
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'regex' : '_23456_',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'regex' : '_6449[6-9]_|_65[0-4][0-9][0-9]_|_655[0-4][0-9]_|_6555[0-1]_',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'regex' : '_6555[2-9]_|_655[6-9][0-9]_|_65[6-9][0-9][0-9]_|_6[6-9][0-9][0-9][0-]_|_[7-9][0-9][0-9][0-9][0-9]_|_1[0-2][0-9][0-9][0-9][0-9]_|_130[0-9][0-9][0-9]_|_1310[0-6][0-9]_|_13107[01]_',
+ },
+ },
+ },
+ }
+
+ for as_path, as_path_config in test_data.items():
+ path = base_path + ['as-path-list', as_path]
+ self.session.set(path + ['description', f'VyOS-ASPATH-{as_path}'])
+ if 'rule' not in as_path_config:
+ continue
+
+ for rule, rule_config in as_path_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'regex' in rule_config:
+ self.session.set(path + ['rule', rule, 'regex', rule_config['regex']])
+
+ self.session.commit()
+
+ config = getFRRconfig('bgp as-path access-list')
+ for as_path, as_path_config in test_data.items():
+ if 'rule' not in as_path_config:
+ continue
+
+ for rule, rule_config in as_path_config['rule'].items():
+ tmp = f'bgp as-path access-list {as_path}'
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['regex']
+
+ self.assertIn(tmp, config)
+
+ def test_community_list(self):
+ test_data = {
+ '100' : {
+ 'rule' : {
+ '4' : {
+ 'action' : 'permit',
+ 'regex' : '.*',
+ },
+ },
+ },
+ '200' : {
+ 'rule' : {
+ '1' : {
+ 'action' : 'deny',
+ 'regex' : '^1:201$',
+ },
+ '2' : {
+ 'action' : 'deny',
+ 'regex' : '1:101$',
+ },
+ '3' : {
+ 'action' : 'deny',
+ 'regex' : '^1:100$',
+ },
+ },
+ },
+ }
+
+ for comm_list, comm_list_config in test_data.items():
+ path = base_path + ['community-list', comm_list]
+ self.session.set(path + ['description', f'VyOS-COMM-{comm_list}'])
+ if 'rule' not in comm_list_config:
+ continue
+
+ for rule, rule_config in comm_list_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'regex' in rule_config:
+ self.session.set(path + ['rule', rule, 'regex', rule_config['regex']])
+
+ self.session.commit()
+
+ config = getFRRconfig('bgp community-list')
+ for comm_list, comm_list_config in test_data.items():
+ if 'rule' not in comm_list_config:
+ continue
+
+ seq = '5'
+ for rule, rule_config in comm_list_config['rule'].items():
+ tmp = f'bgp community-list {comm_list} seq {seq}'
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['regex']
+
+ self.assertIn(tmp, config)
+ seq = int(seq) + 5
+
+ def test_extended_community_list(self):
+ test_data = {
+ 'foo' : {
+ 'rule' : {
+ '4' : {
+ 'action' : 'permit',
+ 'regex' : '.*',
+ },
+ },
+ },
+ '200' : {
+ 'rule' : {
+ '1' : {
+ 'action' : 'deny',
+ 'regex' : '^1:201$',
+ },
+ '2' : {
+ 'action' : 'deny',
+ 'regex' : '1:101$',
+ },
+ '3' : {
+ 'action' : 'deny',
+ 'regex' : '^1:100$',
+ },
+ },
+ },
+ }
+
+ for comm_list, comm_list_config in test_data.items():
+ path = base_path + ['extcommunity-list', comm_list]
+ self.session.set(path + ['description', f'VyOS-EXTCOMM-{comm_list}'])
+ if 'rule' not in comm_list_config:
+ continue
+
+ for rule, rule_config in comm_list_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'regex' in rule_config:
+ self.session.set(path + ['rule', rule, 'regex', rule_config['regex']])
+
+ self.session.commit()
+
+ config = getFRRconfig('bgp extcommunity-list')
+ for comm_list, comm_list_config in test_data.items():
+ if 'rule' not in comm_list_config:
+ continue
+
+ seq = '5'
+ for rule, rule_config in comm_list_config['rule'].items():
+ # if the community is not a number but a name, the expanded
+ # keyword is used
+ expanded = ''
+ if not comm_list.isnumeric():
+ expanded = ' expanded'
+ tmp = f'bgp extcommunity-list{expanded} {comm_list} seq {seq}'
+
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['regex']
+
+ self.assertIn(tmp, config)
+ seq = int(seq) + 5
+
+
+ def test_large_community_list(self):
+ test_data = {
+ 'foo' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'regex' : '667:123:100',
+ },
+ },
+ },
+ 'bar' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'regex' : '65000:120:10',
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'regex' : '65000:120:20',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'regex' : '65000:120:30',
+ },
+ },
+ },
+ }
+
+ for comm_list, comm_list_config in test_data.items():
+ path = base_path + ['large-community-list', comm_list]
+ self.session.set(path + ['description', f'VyOS-LARGECOMM-{comm_list}'])
+ if 'rule' not in comm_list_config:
+ continue
+
+ for rule, rule_config in comm_list_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'regex' in rule_config:
+ self.session.set(path + ['rule', rule, 'regex', rule_config['regex']])
+
+ self.session.commit()
+
+ config = getFRRconfig('bgp large-community-list')
+ for comm_list, comm_list_config in test_data.items():
+ if 'rule' not in comm_list_config:
+ continue
+
+ seq = '5'
+ for rule, rule_config in comm_list_config['rule'].items():
+ tmp = f'bgp large-community-list expanded {comm_list} seq {seq}'
+
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['regex']
+
+ self.assertIn(tmp, config)
+ seq = int(seq) + 5
+
+
+ def test_prefix_list(self):
+ test_data = {
+ 'foo' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'prefix' : '10.0.0.0/8',
+ 'ge' : '16',
+ 'le' : '24',
+ },
+ '20' : {
+ 'action' : 'deny',
+ 'prefix' : '172.16.0.0/12',
+ 'ge' : '16',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'prefix' : '192.168.0.0/16',
+ },
+ },
+ },
+ 'bar' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'prefix' : '10.0.10.0/24',
+ 'ge' : '25',
+ 'le' : '26',
+ },
+ '20' : {
+ 'action' : 'deny',
+ 'prefix' : '10.0.20.0/24',
+ 'le' : '25',
+ },
+ '25' : {
+ 'action' : 'permit',
+ 'prefix' : '10.0.25.0/24',
+ },
+ },
+ },
+ }
+
+ for prefix_list, prefix_list_config in test_data.items():
+ path = base_path + ['prefix-list', prefix_list]
+ self.session.set(path + ['description', f'VyOS-PFX-LIST-{prefix_list}'])
+ if 'rule' not in prefix_list_config:
+ continue
+
+ for rule, rule_config in prefix_list_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'prefix' in rule_config:
+ self.session.set(path + ['rule', rule, 'prefix', rule_config['prefix']])
+ if 'ge' in rule_config:
+ self.session.set(path + ['rule', rule, 'ge', rule_config['ge']])
+ if 'le' in rule_config:
+ self.session.set(path + ['rule', rule, 'le', rule_config['le']])
+
+ self.session.commit()
+
+ config = getFRRconfig('ip prefix-list')
+ for prefix_list, prefix_list_config in test_data.items():
+ if 'rule' not in prefix_list_config:
+ continue
+
+ for rule, rule_config in prefix_list_config['rule'].items():
+ tmp = f'ip prefix-list {prefix_list} seq {rule}'
+
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['prefix']
+
+ if 'ge' in rule_config:
+ tmp += ' ge ' + rule_config['ge']
+ if 'le' in rule_config:
+ tmp += ' le ' + rule_config['le']
+
+ self.assertIn(tmp, config)
+
+
+ def test_prefix_list6(self):
+ test_data = {
+ 'foo' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'prefix' : '2001:db8::/32',
+ 'ge' : '40',
+ 'le' : '48',
+ },
+ '20' : {
+ 'action' : 'deny',
+ 'prefix' : '2001:db8::/32',
+ 'ge' : '48',
+ },
+ '30' : {
+ 'action' : 'permit',
+ 'prefix' : '2001:db8:1000::/64',
+ },
+ },
+ },
+ 'bar' : {
+ 'rule' : {
+ '10' : {
+ 'action' : 'permit',
+ 'prefix' : '2001:db8:100::/40',
+ 'ge' : '48',
+ },
+ '20' : {
+ 'action' : 'permit',
+ 'prefix' : '2001:db8:200::/40',
+ 'ge' : '48',
+ },
+ '25' : {
+ 'action' : 'deny',
+ 'prefix' : '2001:db8:300::/40',
+ 'le' : '64',
+ },
+ },
+ },
+ }
+
+ for prefix_list, prefix_list_config in test_data.items():
+ path = base_path + ['prefix-list6', prefix_list]
+ self.session.set(path + ['description', f'VyOS-PFX-LIST-{prefix_list}'])
+ if 'rule' not in prefix_list_config:
+ continue
+
+ for rule, rule_config in prefix_list_config['rule'].items():
+ if 'action' in rule_config:
+ self.session.set(path + ['rule', rule, 'action', rule_config['action']])
+ if 'prefix' in rule_config:
+ self.session.set(path + ['rule', rule, 'prefix', rule_config['prefix']])
+ if 'ge' in rule_config:
+ self.session.set(path + ['rule', rule, 'ge', rule_config['ge']])
+ if 'le' in rule_config:
+ self.session.set(path + ['rule', rule, 'le', rule_config['le']])
+
+ self.session.commit()
+
+ config = getFRRconfig('ipv6 prefix-list')
+ for prefix_list, prefix_list_config in test_data.items():
+ if 'rule' not in prefix_list_config:
+ continue
+
+ for rule, rule_config in prefix_list_config['rule'].items():
+ tmp = f'ipv6 prefix-list {prefix_list} seq {rule}'
+
+ if rule_config['action'] == 'permit':
+ tmp += ' permit'
+ else:
+ tmp += ' deny'
+
+ tmp += ' ' + rule_config['prefix']
+
+ if 'ge' in rule_config:
+ tmp += ' ge ' + rule_config['ge']
+ if 'le' in rule_config:
+ tmp += ' le ' + rule_config['le']
+
+ self.assertIn(tmp, config)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_bfd.py b/smoketest/scripts/cli/test_protocols_bfd.py
index 044b4b92e..80e5daa7c 100755
--- a/smoketest/scripts/cli/test_protocols_bfd.py
+++ b/smoketest/scripts/cli/test_protocols_bfd.py
@@ -25,38 +25,57 @@ from vyos.util import process_named_running
PROCESS_NAME = 'bfdd'
base_path = ['protocols', 'bfd']
-neighbor_config = {
- '192.0.2.1' : {
+dum_if = 'dum1001'
+peers = {
+ '192.0.2.10' : {
'intv_rx' : '500',
'intv_tx' : '600',
'multihop' : '',
'source_addr': '192.0.2.254',
},
- '192.0.2.2' : {
+ '192.0.2.20' : {
'echo_mode' : '',
'intv_echo' : '100',
- 'intv_mult' : '111',
+ 'intv_mult' : '100',
'intv_rx' : '222',
'intv_tx' : '333',
'shutdown' : '',
- 'source_intf': 'lo',
+ 'source_intf': dum_if,
},
- '2001:db8::1' : {
- 'source_addr': 'fe80::1',
- 'source_intf': 'eth0',
+ '2001:db8::a' : {
+ 'source_addr': '2001:db8::1',
+ 'source_intf': dum_if,
},
- '2001:db8::2' : {
- 'source_addr': 'fe80::1',
+ '2001:db8::b' : {
+ 'source_addr': '2001:db8::1',
'multihop' : '',
},
}
+profiles = {
+ 'foo' : {
+ 'echo_mode' : '',
+ 'intv_echo' : '100',
+ 'intv_mult' : '101',
+ 'intv_rx' : '222',
+ 'intv_tx' : '333',
+ 'shutdown' : '',
+ },
+ 'bar' : {
+ 'intv_mult' : '102',
+ 'intv_rx' : '444',
+ },
+}
+
def getFRRconfig():
return cmd('vtysh -c "show run" | sed -n "/^bfd/,/^!/p"')
def getBFDPeerconfig(peer):
return cmd(f'vtysh -c "show run" | sed -n "/^ {peer}/,/^!/p"')
+def getBFDProfileconfig(profile):
+ return cmd(f'vtysh -c "show run" | sed -n "/^ {profile}/,/^!/p"')
+
class TestProtocolsBFD(unittest.TestCase):
def setUp(self):
self.session = ConfigSession(os.getpid())
@@ -69,8 +88,8 @@ class TestProtocolsBFD(unittest.TestCase):
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
- def test_bfd_simple(self):
- for peer, peer_config in neighbor_config.items():
+ def test_bfd_peer(self):
+ for peer, peer_config in peers.items():
if 'echo_mode' in peer_config:
self.session.set(base_path + ['peer', peer, 'echo-mode'])
if 'intv_echo' in peer_config:
@@ -95,7 +114,7 @@ class TestProtocolsBFD(unittest.TestCase):
# Verify FRR bgpd configuration
frrconfig = getFRRconfig()
- for peer, peer_config in neighbor_config.items():
+ for peer, peer_config in peers.items():
tmp = f'peer {peer}'
if 'multihop' in peer_config:
tmp += f' multihop'
@@ -120,5 +139,43 @@ class TestProtocolsBFD(unittest.TestCase):
if 'shutdown' not in peer_config:
self.assertIn(f' no shutdown', peerconfig)
+ def test_bfd_profile(self):
+ peer = '192.0.2.10'
+
+ for profile, profile_config in profiles.items():
+ if 'echo_mode' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'echo-mode'])
+ if 'intv_echo' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'interval', 'echo-interval', profile_config["intv_echo"]])
+ if 'intv_mult' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'interval', 'multiplier', profile_config["intv_mult"]])
+ if 'intv_rx' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'interval', 'receive', profile_config["intv_rx"]])
+ if 'intv_tx' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'interval', 'transmit', profile_config["intv_tx"]])
+ if 'shutdown' in profile_config:
+ self.session.set(base_path + ['profile', profile, 'shutdown'])
+
+ self.session.set(base_path + ['peer', peer, 'profile', list(profiles)[0]])
+
+ # commit changes
+ self.session.commit()
+
+ # Verify FRR bgpd configuration
+ for profile, profile_config in profiles.items():
+ config = getBFDProfileconfig(f'profile {profile}')
+ if 'echo_mode' in profile_config:
+ self.assertIn(f' echo-mode', config)
+ if 'intv_echo' in profile_config:
+ self.assertIn(f' echo-interval {profile_config["intv_echo"]}', config)
+ if 'intv_mult' in profile_config:
+ self.assertIn(f' detect-multiplier {profile_config["intv_mult"]}', config)
+ if 'intv_rx' in profile_config:
+ self.assertIn(f' receive-interval {profile_config["intv_rx"]}', config)
+ if 'intv_tx' in profile_config:
+ self.assertIn(f' transmit-interval {profile_config["intv_tx"]}', config)
+ if 'shutdown' not in profile_config:
+ self.assertIn(f' no shutdown', config)
+
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 1de51a1fc..7d397b55e 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -128,14 +128,19 @@ peer_group_config = {
},
}
-def getFRRBGPconfig():
- return cmd(f'vtysh -c "show run" | sed -n "/^router bgp {ASN}/,/^!/p"')
+def getFRRBGPconfig(vrf=None):
+ if vrf:
+ return cmd(f'vtysh -c "show run" | sed -n "/^router bgp {ASN} vrf {vrf}$/,/^!/p"')
+ return cmd(f'vtysh -c "show run" | sed -n "/^router bgp {ASN}$/,/^!/p"')
+
+def getFRRBgpAfiConfig(afi):
+ return cmd(f'vtysh -c "show run" | sed -n "/^router bgp {ASN}$/,/^!/p" | sed -n "/^ address-family {afi} unicast/,/^ exit-address-family/p"')
def getFRRBGPVNIconfig(vni):
- return cmd(f'vtysh -c "show run" | sed -n "/^ vni {vni}/,/^!/p"')
+ return cmd(f'vtysh -c "show run" | sed -n "/^ vni {vni}$/,/^!/p"')
def getFRRRPKIconfig():
- return cmd(f'vtysh -c "show run" | sed -n "/^rpki/,/^!/p"')
+ return cmd(f'vtysh -c "show run" | sed -n "/^rpki$/,/^!/p"')
class TestProtocolsBGP(unittest.TestCase):
def setUp(self):
@@ -218,15 +223,26 @@ class TestProtocolsBGP(unittest.TestCase):
router_id = '127.0.0.1'
local_pref = '500'
stalepath_time = '60'
+ max_path_v4 = '2'
+ max_path_v4ibgp = '4'
+ max_path_v6 = '8'
+ max_path_v6ibgp = '16'
self.session.set(base_path + ['parameters', 'router-id', router_id])
self.session.set(base_path + ['parameters', 'log-neighbor-changes'])
- # Default local preference (higher=more preferred)
+ # Default local preference (higher = more preferred, default value is 100)
self.session.set(base_path + ['parameters', 'default', 'local-pref', local_pref])
# Deactivate IPv4 unicast for a peer by default
self.session.set(base_path + ['parameters', 'default', 'no-ipv4-unicast'])
self.session.set(base_path + ['parameters', 'graceful-restart', 'stalepath-time', stalepath_time])
self.session.set(base_path + ['parameters', 'graceful-shutdown'])
+ self.session.set(base_path + ['parameters', 'ebgp-requires-policy'])
+
+ # AFI maximum path support
+ self.session.set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ebgp', max_path_v4])
+ self.session.set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ibgp', max_path_v4ibgp])
+ self.session.set(base_path + ['address-family', 'ipv6-unicast', 'maximum-paths', 'ebgp', max_path_v6])
+ self.session.set(base_path + ['address-family', 'ipv6-unicast', 'maximum-paths', 'ibgp', max_path_v6ibgp])
# commit changes
self.session.commit()
@@ -240,6 +256,15 @@ class TestProtocolsBGP(unittest.TestCase):
self.assertIn(f' no bgp default ipv4-unicast', frrconfig)
self.assertIn(f' bgp graceful-restart stalepath-time {stalepath_time}', frrconfig)
self.assertIn(f' bgp graceful-shutdown', frrconfig)
+ self.assertNotIn(f'bgp ebgp-requires-policy', frrconfig)
+
+ afiv4_config = getFRRBgpAfiConfig('ipv4')
+ self.assertIn(f' maximum-paths {max_path_v4}', afiv4_config)
+ self.assertIn(f' maximum-paths ibgp {max_path_v4ibgp}', afiv4_config)
+
+ afiv6_config = getFRRBgpAfiConfig('ipv6')
+ self.assertIn(f' maximum-paths {max_path_v6}', afiv6_config)
+ self.assertIn(f' maximum-paths ibgp {max_path_v6ibgp}', afiv6_config)
def test_bgp_02_neighbors(self):
@@ -388,7 +413,7 @@ class TestProtocolsBGP(unittest.TestCase):
}
# We want to redistribute ...
- redistributes = ['connected', 'kernel', 'ospf', 'rip', 'static']
+ redistributes = ['connected', 'isis', 'kernel', 'ospf', 'rip', 'static']
for redistribute in redistributes:
self.session.set(base_path + ['address-family', 'ipv4-unicast',
'redistribute', redistribute])
@@ -453,6 +478,9 @@ class TestProtocolsBGP(unittest.TestCase):
frrconfig = getFRRBGPconfig()
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' address-family ipv6 unicast', frrconfig)
+ # T2100: By default ebgp-requires-policy is disabled to keep VyOS
+ # 1.3 and 1.2 backwards compatibility
+ self.assertIn(f' no bgp ebgp-requires-policy', frrconfig)
for redistribute in redistributes:
# FRR calls this OSPF6
@@ -525,5 +553,27 @@ class TestProtocolsBGP(unittest.TestCase):
self.assertIn(f' advertise-default-gw', vniconfig)
self.assertIn(f' advertise-svi-ip', vniconfig)
+ def test_bgp_08_vrf_simple(self):
+ router_id = '127.0.0.3'
+ vrfs = ['red', 'green', 'blue']
+ # It is safe to assume that when the basic VRF test works, all
+ # other OSPF related features work, as we entirely inherit the CLI
+ # templates and Jinja2 FRR template.
+ table = '1000'
+ for vrf in vrfs:
+ vrf_base = ['vrf', 'name', vrf]
+ self.session.set(vrf_base + ['table', table])
+ self.session.set(vrf_base + ['protocols', 'bgp', ASN, 'parameters', 'router-id', router_id])
+ table = str(int(table) + 1000)
+
+ self.session.commit()
+
+ for vrf in vrfs:
+ # Verify FRR bgpd configuration
+ frrconfig = getFRRBGPconfig(vrf)
+
+ self.assertIn(f'router bgp {ASN} vrf {vrf}', frrconfig)
+ self.assertIn(f' bgp router-id {router_id}', frrconfig)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index ce30f6a7d..532d84cc8 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -27,8 +27,10 @@ base_path = ['protocols', 'ospf']
route_map = 'foo-bar-baz10'
-def getFRROSPFconfig():
- return cmd('vtysh -c "show run" | sed -n "/router ospf/,/^!/p"')
+def getFRRconfig(vrf=None):
+ if vrf:
+ return cmd(f'vtysh -c "show run" | sed -n "/^router ospf vrf {vrf}$/,/^!/p"')
+ return cmd('vtysh -c "show run" | sed -n "/^router ospf$/,/^!/p"')
def getFRRInterfaceConfig(interface):
return cmd(f'vtysh -c "show run" | sed -n "/^interface {interface}$/,/^!/p"')
@@ -45,6 +47,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.delete(['policy', 'route-map', route_map])
self.session.delete(base_path)
+
self.session.commit()
del self.session
@@ -54,12 +57,11 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig)
self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults
-
def test_ospf_02_simple(self):
router_id = '127.0.0.1'
abr_type = 'ibm'
@@ -76,7 +78,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' auto-cost reference-bandwidth {bandwidth}', frrconfig)
self.assertIn(f' ospf router-id {router_id}', frrconfig)
@@ -88,7 +90,7 @@ class TestProtocolsOSPF(unittest.TestCase):
def test_ospf_03_access_list(self):
acl = '100'
seq = '10'
- protocols = ['bgp', 'connected', 'kernel', 'rip', 'static']
+ protocols = ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static']
self.session.set(['policy', 'access-list', acl, 'rule', seq, 'action', 'permit'])
self.session.set(['policy', 'access-list', acl, 'rule', seq, 'source', 'any'])
@@ -100,7 +102,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults
for ptotocol in protocols:
@@ -121,7 +123,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults
self.assertIn(f' default-information originate metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig)
@@ -131,7 +133,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f' default-information originate always metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig)
@@ -158,7 +160,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' mpls-te on', frrconfig)
self.assertIn(f' mpls-te router-address 0.0.0.0', frrconfig) # default
@@ -173,7 +175,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.set(base_path + ['distance', 'ospf', 'inter-area', inter_area])
self.session.commit()
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f' distance ospf intra-area {intra_area} inter-area {inter_area} external {external}', frrconfig)
@@ -189,7 +191,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
for neighbor in neighbors:
self.assertIn(f' neighbor {neighbor} priority {priority} poll-interval {poll_interval}', frrconfig) # default
@@ -205,7 +207,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' passive-interface default', frrconfig) # default
for interface in interfaces:
@@ -215,7 +217,7 @@ class TestProtocolsOSPF(unittest.TestCase):
def test_ospf_08_redistribute(self):
metric = '15'
metric_type = '1'
- redistribute = ['bgp', 'connected', 'kernel', 'rip', 'static']
+ redistribute = ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static']
for protocol in redistribute:
self.session.set(base_path + ['redistribute', protocol, 'metric', metric])
@@ -227,7 +229,7 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
self.assertIn(f'router ospf', frrconfig)
for protocol in redistribute:
if protocol in ['kernel', 'static']:
@@ -235,6 +237,7 @@ class TestProtocolsOSPF(unittest.TestCase):
else:
self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig)
+
def test_ospf_09_virtual_link(self):
networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
area = '10'
@@ -257,13 +260,27 @@ class TestProtocolsOSPF(unittest.TestCase):
self.session.commit()
# Verify FRR ospfd configuration
- frrconfig = getFRROSPFconfig()
+ frrconfig = getFRRconfig()
+ import pprint
+ # From time to time the CI fails with an error like:
+ # ======================================================================
+ # FAIL: test_ospf_09_virtual_link (__main__.TestProtocolsOSPF)
+ # ----------------------------------------------------------------------
+ # Traceback (most recent call last):
+ # File "/usr/libexec/vyos/tests/smoke/cli/test_protocols_ospf.py", line 261, in test_ospf_09_virtual_link
+ # self.assertIn(f'router ospf', frrconfig)
+ # AssertionError: 'router ospf' not found in ''
+ #
+ # Add some debug code so we can find the root cause
+ pprint.pprint(frrconfig)
+
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' area {area} shortcut {shortcut}', frrconfig)
self.assertIn(f' area {area} virtual-link {virtual_link} hello-interval {hello} retransmit-interval {retransmit} transmit-delay {transmit} dead-interval {dead}', frrconfig)
for network in networks:
self.assertIn(f' network {network} area {area}', frrconfig)
+
def test_ospf_10_interface_configureation(self):
interfaces = Section.interfaces('ethernet')
password = 'vyos1234'
@@ -295,5 +312,37 @@ class TestProtocolsOSPF(unittest.TestCase):
self.assertIn(f' ip ospf priority {priority}', config)
self.assertIn(f' bandwidth {bandwidth}', config)
+
+ def test_ospf_11_vrfs(self):
+ vrfs = ['red', 'green', 'blue']
+ # It is safe to assume that when the basic VRF test works, all
+ # other OSPF related features work, as we entirely inherit the CLI
+ # templates and Jinja2 FRR template.
+ table = '1000'
+ for vrf in vrfs:
+ vrf_base = ['vrf', 'name', vrf]
+ self.session.set(vrf_base + ['table', table])
+ self.session.set(vrf_base + ['protocols', 'ospf'])
+ table = str(int(table) + 1000)
+
+ # Also set a default VRF OSPF config
+ self.session.set(base_path)
+ self.session.commit()
+
+ # Verify FRR ospfd configuration
+ frrconfig = getFRRconfig()
+ self.assertIn(f'router ospf', frrconfig)
+ self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig)
+ self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults
+
+ for vrf in vrfs:
+ frrconfig = getFRRconfig(vrf)
+ self.assertIn(f'router ospf vrf {vrf}', frrconfig)
+ self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig)
+ self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults
+
+ self.session.delete(['vrf', 'name', vrf])
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py
index 297d5d996..754c4488f 100755
--- a/smoketest/scripts/cli/test_protocols_ospfv3.py
+++ b/smoketest/scripts/cli/test_protocols_ospfv3.py
@@ -25,10 +25,15 @@ from vyos.util import process_named_running
PROCESS_NAME = 'ospf6d'
base_path = ['protocols', 'ospfv3']
+router_id = '192.0.2.1'
+default_area = '0'
def getFRROSPFconfig():
return cmd('vtysh -c "show run" | sed -n "/router ospf6/,/^!/p"')
+def getFRRIFconfig(iface):
+ return cmd(f'vtysh -c "show run" | sed -n "/^interface {iface}/,/^!/p"')
+
class TestProtocolsOSPFv3(unittest.TestCase):
def setUp(self):
self.session = ConfigSession(os.getpid())
@@ -43,23 +48,21 @@ class TestProtocolsOSPFv3(unittest.TestCase):
def test_ospfv3_01_basic(self):
- area = '0'
seq = '10'
prefix = '2001:db8::/32'
acl_name = 'foo-acl-100'
- router_id = '192.0.2.1'
self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'action', 'permit'])
self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'source', 'any'])
self.session.set(base_path + ['parameters', 'router-id', router_id])
- self.session.set(base_path + ['area', area, 'range', prefix, 'advertise'])
- self.session.set(base_path + ['area', area, 'export-list', acl_name])
- self.session.set(base_path + ['area', area, 'import-list', acl_name])
+ self.session.set(base_path + ['area', default_area, 'range', prefix, 'advertise'])
+ self.session.set(base_path + ['area', default_area, 'export-list', acl_name])
+ self.session.set(base_path + ['area', default_area, 'import-list', acl_name])
interfaces = Section.interfaces('ethernet')
for interface in interfaces:
- self.session.set(base_path + ['area', area, 'interface', interface])
+ self.session.set(base_path + ['area', default_area, 'interface', interface])
# commit changes
self.session.commit()
@@ -67,13 +70,13 @@ class TestProtocolsOSPFv3(unittest.TestCase):
# Verify FRR ospfd configuration
frrconfig = getFRROSPFconfig()
self.assertIn(f'router ospf6', frrconfig)
- self.assertIn(f' area {area} range {prefix}', frrconfig)
+ self.assertIn(f' area {default_area} range {prefix}', frrconfig)
self.assertIn(f' ospf6 router-id {router_id}', frrconfig)
- self.assertIn(f' area {area} import-list {acl_name}', frrconfig)
- self.assertIn(f' area {area} export-list {acl_name}', frrconfig)
+ self.assertIn(f' area {default_area} import-list {acl_name}', frrconfig)
+ self.assertIn(f' area {default_area} export-list {acl_name}', frrconfig)
for interface in interfaces:
- self.assertIn(f' interface {interface} area {area}', frrconfig)
+ self.assertIn(f' interface {interface} area {default_area}', frrconfig)
self.session.delete(['policy', 'access-list6', acl_name])
@@ -118,6 +121,46 @@ class TestProtocolsOSPFv3(unittest.TestCase):
for protocol in redistribute:
self.assertIn(f' redistribute {protocol} route-map {route_map}', frrconfig)
+ def test_ospfv3_0104_interfaces(self):
+
+ self.session.set(base_path + ['parameters', 'router-id', router_id])
+ self.session.set(base_path + ['area', default_area])
+
+ cost = '100'
+ priority = '10'
+ interfaces = Section.interfaces('ethernet')
+ for interface in interfaces:
+ if_base = base_path + ['interface', interface]
+ self.session.set(if_base + ['bfd'])
+ self.session.set(if_base + ['cost', cost])
+ self.session.set(if_base + ['instance-id', '0'])
+ self.session.set(if_base + ['mtu-ignore'])
+ self.session.set(if_base + ['network', 'point-to-point'])
+ self.session.set(if_base + ['passive'])
+ self.session.set(if_base + ['priority', priority])
+ cost = str(int(cost) + 10)
+ priority = str(int(priority) + 5)
+
+ # commit changes
+ self.session.commit()
+
+ # Verify FRR ospfd configuration
+ frrconfig = getFRROSPFconfig()
+ self.assertIn(f'router ospf6', frrconfig)
+
+ cost = '100'
+ priority = '10'
+ for interface in interfaces:
+ if_config = getFRRIFconfig(interface)
+ self.assertIn(f'interface {interface}', if_config)
+ self.assertIn(f' ipv6 ospf6 bfd', if_config)
+ self.assertIn(f' ipv6 ospf6 cost {cost}', if_config)
+ self.assertIn(f' ipv6 ospf6 mtu-ignore', if_config)
+ self.assertIn(f' ipv6 ospf6 network point-to-point', if_config)
+ self.assertIn(f' ipv6 ospf6 passive', if_config)
+ self.assertIn(f' ipv6 ospf6 priority {priority}', if_config)
+ cost = str(int(cost) + 10)
+ priority = str(int(priority) + 5)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_rip.py b/smoketest/scripts/cli/test_protocols_rip.py
index 2c5c9030a..f42ea0c0a 100755
--- a/smoketest/scripts/cli/test_protocols_rip.py
+++ b/smoketest/scripts/cli/test_protocols_rip.py
@@ -71,7 +71,7 @@ class TestProtocolsRIP(unittest.TestCase):
interfaces = Section.interfaces('ethernet')
neighbors = ['1.2.3.4', '1.2.3.5', '1.2.3.6']
networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
- redistribute = ['bgp', 'connected', 'kernel', 'ospf', 'static']
+ redistribute = ['bgp', 'connected', 'isis', 'kernel', 'ospf', 'static']
timer_garbage = '888'
timer_timeout = '1000'
timer_update = '90'
diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py
index cf591f060..28ae5e2dd 100755
--- a/smoketest/scripts/cli/test_protocols_static.py
+++ b/smoketest/scripts/cli/test_protocols_static.py
@@ -21,6 +21,7 @@ from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos.template import is_ipv6
from vyos.util import cmd
+from vyos.util import get_interface_config
base_path = ['protocols', 'static']
vrf_path = ['protocols', 'vrf']
@@ -85,7 +86,6 @@ routes = {
},
}
-vrfs = ['red', 'green', 'blue']
tables = ['80', '81', '82']
class StaticRouteTest(unittest.TestCase):
@@ -99,9 +99,6 @@ class StaticRouteTest(unittest.TestCase):
route_type = 'route6'
self.session.delete(base_path + [route_type, route])
- for vrf in vrfs:
- self.session.delete(vrf_path + [vrf])
-
for table in tables:
self.session.delete(base_path + ['table', table])
@@ -290,47 +287,65 @@ class StaticRouteTest(unittest.TestCase):
def test_protocols_vrf_static(self):
- for vrf in vrfs:
+ # Create VRF instances and apply the static routes from above to FRR.
+ # Re-read the configured routes and match them if they are programmed
+ # properly. This also includes VRF leaking
+ vrfs = {
+ 'red' : { 'table' : '1000' },
+ 'green' : { 'table' : '2000' },
+ 'blue' : { 'table' : '3000' },
+ }
+
+ for vrf, vrf_config in vrfs.items():
+ vrf_base_path = ['vrf', 'name', vrf]
+ self.session.set(vrf_base_path + ['table', vrf_config['table']])
+
for route, route_config in routes.items():
route_type = 'route'
if is_ipv6(route):
route_type = 'route6'
- base = vrf_path + [vrf, 'static', route_type, route]
+ route_base_path = vrf_base_path + ['protocols', 'static', route_type, route]
if 'next_hop' in route_config:
for next_hop, next_hop_config in route_config['next_hop'].items():
- self.session.set(base + ['next-hop', next_hop])
+ self.session.set(route_base_path + ['next-hop', next_hop])
if 'disable' in next_hop_config:
- self.session.set(base + ['next-hop', next_hop, 'disable'])
+ self.session.set(route_base_path + ['next-hop', next_hop, 'disable'])
if 'distance' in next_hop_config:
- self.session.set(base + ['next-hop', next_hop, 'distance', next_hop_config['distance']])
+ self.session.set(route_base_path + ['next-hop', next_hop, 'distance', next_hop_config['distance']])
if 'interface' in next_hop_config:
- self.session.set(base + ['next-hop', next_hop, 'interface', next_hop_config['interface']])
+ self.session.set(route_base_path + ['next-hop', next_hop, 'interface', next_hop_config['interface']])
if 'vrf' in next_hop_config:
- self.session.set(base + ['next-hop', next_hop, 'vrf', next_hop_config['vrf']])
+ self.session.set(route_base_path + ['next-hop', next_hop, 'vrf', next_hop_config['vrf']])
if 'interface' in route_config:
for interface, interface_config in route_config['interface'].items():
- self.session.set(base + ['interface', interface])
+ self.session.set(route_base_path + ['interface', interface])
if 'disable' in interface_config:
- self.session.set(base + ['interface', interface, 'disable'])
+ self.session.set(route_base_path + ['interface', interface, 'disable'])
if 'distance' in interface_config:
- self.session.set(base + ['interface', interface, 'distance', interface_config['distance']])
+ self.session.set(route_base_path + ['interface', interface, 'distance', interface_config['distance']])
if 'vrf' in interface_config:
- self.session.set(base + ['interface', interface, 'vrf', interface_config['vrf']])
+ self.session.set(route_base_path + ['interface', interface, 'vrf', interface_config['vrf']])
if 'blackhole' in route_config:
- self.session.set(base + ['blackhole'])
+ self.session.set(route_base_path + ['blackhole'])
if 'distance' in route_config['blackhole']:
- self.session.set(base + ['blackhole', 'distance', route_config['blackhole']['distance']])
+ self.session.set(route_base_path + ['blackhole', 'distance', route_config['blackhole']['distance']])
if 'tag' in route_config['blackhole']:
- self.session.set(base + ['blackhole', 'tag', route_config['blackhole']['tag']])
+ self.session.set(route_base_path + ['blackhole', 'tag', route_config['blackhole']['tag']])
# commit changes
self.session.commit()
- for vrf in vrfs:
+ for vrf, vrf_config in vrfs.items():
+ tmp = get_interface_config(vrf)
+
+ # Compare VRF table ID
+ self.assertEqual(tmp['linkinfo']['info_data']['table'], int(vrf_config['table']))
+ self.assertEqual(tmp['linkinfo']['info_kind'], 'vrf')
+
# Verify FRR bgpd configuration
frrconfig = getFRRCconfig(vrf)
self.assertIn(f'vrf {vrf}', frrconfig)
@@ -380,6 +395,7 @@ class StaticRouteTest(unittest.TestCase):
self.assertIn(tmp, frrconfig)
+ self.session.delete(['vrf'])
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index db7b2dda4..e74e22a5c 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -200,6 +200,7 @@ class TestServiceDHCPServer(unittest.TestCase):
def test_dhcp_single_pool_static_mapping(self):
shared_net_name = 'SMOKE-2'
+ domain_name = 'private'
pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
# we use the first subnet IP address as default gateway
diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py
index 319891a94..a364eee11 100755
--- a/smoketest/scripts/cli/test_service_dhcpv6-server.py
+++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py
@@ -151,5 +151,26 @@ class TestServiceDHCPServer(unittest.TestCase):
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
+ def test_global_nameserver(self):
+ shared_net_name = 'SMOKE-3'
+ ns_global_1 = '2001:db8::1111'
+ ns_global_2 = '2001:db8::2222'
+
+ self.session.set(base_path + ['global-parameters', 'name-server', ns_global_1])
+ self.session.set(base_path + ['global-parameters', 'name-server', ns_global_2])
+ self.session.set(base_path + ['shared-network-name', shared_net_name, 'subnet', subnet])
+
+ # commit changes
+ self.session.commit()
+
+ config = read_file(DHCPD_CONF)
+ self.assertIn(f'option dhcp6.name-servers {ns_global_1};', config)
+ self.assertIn(f'option dhcp6.name-servers {ns_global_2};', config)
+ self.assertIn(f'subnet6 {subnet}' + r' {', config)
+ self.assertIn(f'set shared-networkname = "{shared_net_name}";', config)
+
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py
index a4bb6e9f9..e8f9facbb 100755
--- a/smoketest/scripts/cli/test_service_pppoe-server.py
+++ b/smoketest/scripts/cli/test_service_pppoe-server.py
@@ -144,7 +144,8 @@ class TestServicePPPoEServer(BasicAccelPPPTest.BaseTest):
start = '192.0.2.10'
stop = '192.0.2.20'
- start_stop = f'{start}-{stop}'
+ stop_octet = stop.split('.')[3]
+ start_stop = f'{start}-{stop_octet}'
self.set(['client-ip-pool', 'start', start])
self.set(['client-ip-pool', 'stop', stop])
diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py
index 8e977d407..aac115663 100755
--- a/smoketest/scripts/cli/test_vrf.py
+++ b/smoketest/scripts/cli/test_vrf.py
@@ -33,12 +33,6 @@ from vyos.validate import is_intf_addr_assigned
base_path = ['vrf']
vrfs = ['red', 'green', 'blue', 'foo-bar', 'baz_foo']
-def get_vrf_ipv4_routes(vrf):
- return json.loads(cmd(f'ip -4 -j route show vrf {vrf}'))
-
-def get_vrf_ipv6_routes(vrf):
- return json.loads(cmd(f'ip -6 -j route show vrf {vrf}'))
-
class VRFTest(unittest.TestCase):
_interfaces = []
diff --git a/src/completion/list_bgp_peer_groups.sh b/src/completion/list_bgp_peer_groups.sh
new file mode 100755
index 000000000..4503d608f
--- /dev/null
+++ b/src/completion/list_bgp_peer_groups.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# 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/>.
+
+# Return BGP peer-groups from CLI
+
+declare -a vals
+eval "bgp_as=$(cli-shell-api listNodes protocols bgp)"
+eval "vals=($(cli-shell-api listNodes protocols bgp $bgp_as peer-group))"
+
+echo -n ${vals[@]}
+exit 0
diff --git a/src/conf_mode/interfaces-erspan.py b/src/conf_mode/interfaces-erspan.py
index 2d65b834c..97ae3cf55 100755
--- a/src/conf_mode/interfaces-erspan.py
+++ b/src/conf_mode/interfaces-erspan.py
@@ -48,7 +48,7 @@ def get_config(config=None):
conf = Config()
base = ['interfaces', 'erspan']
erspan = get_interface_dict(conf, base)
-
+
tmp = leaf_node_changed(conf, ['encapsulation'])
if tmp:
erspan.update({'encapsulation_changed': {}})
@@ -58,30 +58,30 @@ def get_config(config=None):
def verify(erspan):
if 'deleted' in erspan:
return None
-
+
if 'encapsulation' not in erspan:
raise ConfigError('Unable to detect the following ERSPAN tunnel encapsulation'\
'{ifname}!'.format(**erspan))
verify_mtu_ipv6(erspan)
verify_tunnel(erspan)
-
+
key = dict_search('parameters.ip.key',erspan)
if key == None:
raise ConfigError('parameters.ip.key is mandatory for ERSPAN tunnel')
-
+
def generate(erspan):
return None
def apply(erspan):
- if 'deleted' in erspan or 'encapsulation_changed' in erspan:
- if erspan['ifname'] in interfaces():
- tmp = Interface(erspan['ifname'])
- tmp.remove()
- if 'deleted' in erspan:
- return None
-
+ if 'deleted' in erspan or 'encapsulation_changed' in erspan:
+ if erspan['ifname'] in interfaces():
+ tmp = Interface(erspan['ifname'])
+ tmp.remove()
+ if 'deleted' in erspan:
+ return None
+
dispatch = {
'erspan': ERSpanIf,
'ip6erspan': ER6SpanIf
@@ -90,14 +90,8 @@ def apply(erspan):
# We need to re-map the tunnel encapsulation proto to a valid interface class
encap = erspan['encapsulation']
klass = dispatch[encap]
-
- conf = deepcopy(erspan)
-
- conf.update(klass.get_config())
-
- del conf['ifname']
-
- erspan_tunnel = klass(erspan['ifname'],**conf)
+
+ erspan_tunnel = klass(**erspan)
erspan_tunnel.change_options()
erspan_tunnel.update(erspan)
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py
index e7f0cd6a5..378f400b8 100755
--- a/src/conf_mode/interfaces-ethernet.py
+++ b/src/conf_mode/interfaces-ethernet.py
@@ -30,6 +30,7 @@ from vyos.configverify import verify_mtu
from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_vlan_config
from vyos.configverify import verify_vrf
+from vyos.ethtool import Ethtool
from vyos.ifconfig import EthernetIf
from vyos.template import render
from vyos.util import call
@@ -76,10 +77,37 @@ def verify(ethernet):
verify_mirror(ethernet)
# verify offloading capabilities
- if 'offload' in ethernet and 'rps' in ethernet['offload']:
+ if dict_search('offload.rps', ethernet) != None:
if not os.path.exists(f'/sys/class/net/{ifname}/queues/rx-0/rps_cpus'):
raise ConfigError('Interface does not suport RPS!')
+ driver = EthernetIf(ifname).get_driver_name()
+ # T3342 - Xen driver requires special treatment
+ if driver == 'vif':
+ if int(ethernet['mtu']) > 1500 and dict_search('offload.sg', ethernet) == None:
+ raise ConfigError('Xen netback drivers requires scatter-gatter offloading '\
+ 'for MTU size larger then 1500 bytes')
+
+ ethtool = Ethtool(ifname)
+ if 'ring_buffer' in ethernet:
+ max_rx = ethtool.get_rx_buffer()
+ if not max_rx:
+ raise ConfigError('Driver does not support RX ring-buffer configuration!')
+
+ max_tx = ethtool.get_tx_buffer()
+ if not max_tx:
+ raise ConfigError('Driver does not support TX ring-buffer configuration!')
+
+ rx = dict_search('ring_buffer.rx', ethernet)
+ if rx and int(rx) > int(max_rx):
+ raise ConfigError(f'Driver only supports a maximum RX ring-buffer '\
+ f'size of "{max_rx}" bytes!')
+
+ tx = dict_search('ring_buffer.tx', ethernet)
+ if tx and int(tx) > int(max_tx):
+ raise ConfigError(f'Driver only supports a maximum TX ring-buffer '\
+ f'size of "{max_tx}" bytes!')
+
# XDP requires multiple TX queues
if 'xdp' in ethernet:
queues = glob(f'/sys/class/net/{ifname}/queues/tx-*')
diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py
index 979a5612e..2a63b60aa 100755
--- a/src/conf_mode/interfaces-geneve.py
+++ b/src/conf_mode/interfaces-geneve.py
@@ -72,18 +72,8 @@ def apply(geneve):
g.remove()
if 'deleted' not in geneve:
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = GeneveIf.get_config()
-
- # Assign GENEVE instance configuration parameters to config dict
- conf['vni'] = geneve['vni']
- conf['remote'] = geneve['remote']
-
# Finally create the new interface
- g = GeneveIf(geneve['ifname'], **conf)
+ g = GeneveIf(**geneve)
g.update(geneve)
return None
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index 7b3afa058..9b6ddd5aa 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -34,7 +34,6 @@ airbag.enable()
k_mod = ['l2tp_eth', 'l2tp_netlink', 'l2tp_ip', 'l2tp_ip6']
-
def get_config(config=None):
"""
Retrive CLI config as dictionary. Dictionary can never be empty, as at least the
@@ -65,15 +64,15 @@ def verify(l2tpv3):
interface = l2tpv3['ifname']
- for key in ['local_ip', 'remote_ip', 'tunnel_id', 'peer_tunnel_id',
+ for key in ['source_address', 'remote', 'tunnel_id', 'peer_tunnel_id',
'session_id', 'peer_session_id']:
if key not in l2tpv3:
tmp = key.replace('_', '-')
- raise ConfigError(f'L2TPv3 {tmp} must be configured!')
+ raise ConfigError(f'Missing mandatory L2TPv3 option: "{tmp}"!')
- if not is_addr_assigned(l2tpv3['local_ip']):
- raise ConfigError('L2TPv3 local-ip address '
- '"{local_ip}" is not configured!'.format(**l2tpv3))
+ if not is_addr_assigned(l2tpv3['source_address']):
+ raise ConfigError('L2TPv3 source-address address "{source_address}" '
+ 'not configured on any interface!'.format(**l2tpv3))
verify_mtu_ipv6(l2tpv3)
verify_address(l2tpv3)
@@ -83,34 +82,16 @@ def generate(l2tpv3):
return None
def apply(l2tpv3):
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = L2TPv3If.get_config()
-
# Check if L2TPv3 interface already exists
if l2tpv3['ifname'] in interfaces():
# L2TPv3 is picky when changing tunnels/sessions, thus we can simply
# always delete it first.
- conf['session_id'] = l2tpv3['session_id']
- conf['tunnel_id'] = l2tpv3['tunnel_id']
- l = L2TPv3If(l2tpv3['ifname'], **conf)
+ l = L2TPv3If(**l2tpv3)
l.remove()
if 'deleted' not in l2tpv3:
- conf['peer_tunnel_id'] = l2tpv3['peer_tunnel_id']
- conf['local_port'] = l2tpv3['source_port']
- conf['remote_port'] = l2tpv3['destination_port']
- conf['encapsulation'] = l2tpv3['encapsulation']
- conf['local_address'] = l2tpv3['local_ip']
- conf['remote_address'] = l2tpv3['remote_ip']
- conf['session_id'] = l2tpv3['session_id']
- conf['tunnel_id'] = l2tpv3['tunnel_id']
- conf['peer_session_id'] = l2tpv3['peer_session_id']
-
# Finally create the new interface
- l = L2TPv3If(l2tpv3['ifname'], **conf)
+ l = L2TPv3If(**l2tpv3)
l.update(l2tpv3)
return None
diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py
index bfebed7e4..eab69f36e 100755
--- a/src/conf_mode/interfaces-macsec.py
+++ b/src/conf_mode/interfaces-macsec.py
@@ -115,17 +115,9 @@ def apply(macsec):
os.unlink(wpa_suppl_conf.format(**macsec))
else:
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = MACsecIf.get_config()
- conf['source_interface'] = macsec['source_interface']
- conf['security_cipher'] = macsec['security']['cipher']
-
# It is safe to "re-create" the interface always, there is a sanity
# check that the interface will only be create if its non existent
- i = MACsecIf(macsec['ifname'], **conf)
+ i = MACsecIf(**macsec)
i.update(macsec)
call('systemctl restart wpa_supplicant-macsec@{source_interface}'
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index ee6f05fcd..4afb85526 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -502,10 +502,7 @@ def apply(openvpn):
# existed - nevertheless, spawn new OpenVPN process
call(f'systemctl start openvpn@{interface}.service')
- conf = VTunIf.get_config()
- conf['device_type'] = openvpn['device_type']
-
- o = VTunIf(interface, **conf)
+ o = VTunIf(**openvpn)
o.update(openvpn)
return None
diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py
index ddbef56ac..34a054837 100755
--- a/src/conf_mode/interfaces-pseudo-ethernet.py
+++ b/src/conf_mode/interfaces-pseudo-ethernet.py
@@ -75,19 +75,9 @@ def apply(peth):
if 'mode_old' in peth:
MACVLANIf(peth['ifname']).remove()
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = MACVLANIf.get_config()
-
- # Assign MACVLAN instance configuration parameters to config dict
- conf['source_interface'] = peth['source_interface']
- conf['mode'] = peth['mode']
-
# It is safe to "re-create" the interface always, there is a sanity check
# that the interface will only be create if its non existent
- p = MACVLANIf(peth['ifname'], **conf)
+ p = MACVLANIf(**peth)
p.update(peth)
return None
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index 034bd6dd1..cab94a5b0 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -31,16 +31,10 @@ from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_vrf
from vyos.configverify import verify_tunnel
from vyos.ifconfig import Interface
-from vyos.ifconfig import GREIf
-from vyos.ifconfig import GRETapIf
-from vyos.ifconfig import IPIPIf
-from vyos.ifconfig import IP6GREIf
-from vyos.ifconfig import IPIP6If
-from vyos.ifconfig import IP6IP6If
-from vyos.ifconfig import SitIf
-from vyos.ifconfig import Sit6RDIf
+from vyos.ifconfig import TunnelIf
from vyos.template import is_ipv4
from vyos.template import is_ipv6
+from vyos.util import get_interface_config
from vyos.util import dict_search
from vyos import ConfigError
from vyos import airbag
@@ -79,8 +73,8 @@ def verify(tunnel):
return None
if 'encapsulation' not in tunnel:
- raise ConfigError('Must configure the tunnel encapsulation for '\
- '{ifname}!'.format(**tunnel))
+ error = 'Must configure encapsulation for "{ifname}"!'
+ raise ConfigError(error.format(**tunnel))
verify_mtu_ipv6(tunnel)
verify_address(tunnel)
@@ -103,68 +97,26 @@ def generate(tunnel):
return None
def apply(tunnel):
- if 'deleted' in tunnel or 'encapsulation_changed' in tunnel:
- if tunnel['ifname'] in interfaces():
- tmp = Interface(tunnel['ifname'])
+ interface = tunnel['ifname']
+ # If a gretap tunnel is already existing we can not "simply" change local or
+ # remote addresses. This returns "Operation not supported" by the Kernel.
+ # There is no other solution to destroy and recreate the tunnel.
+ encap = ''
+ remote = ''
+ tmp = get_interface_config(interface)
+ if tmp:
+ encap = dict_search('linkinfo.info_kind', tmp)
+ remote = dict_search('linkinfo.info_data.remote', tmp)
+
+ if ('deleted' in tunnel or 'encapsulation_changed' in tunnel or
+ encap in ['gretap', 'ip6gretap'] or remote in ['any']):
+ if interface in interfaces():
+ tmp = Interface(interface)
tmp.remove()
if 'deleted' in tunnel:
return None
- dispatch = {
- 'gre': GREIf,
- 'gre-bridge': GRETapIf,
- 'ipip': IPIPIf,
- 'ipip6': IPIP6If,
- 'ip6ip6': IP6IP6If,
- 'ip6gre': IP6GREIf,
- 'sit': SitIf,
- }
-
- # We need to re-map the tunnel encapsulation proto to a valid interface class
- encap = tunnel['encapsulation']
- klass = dispatch[encap]
-
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = klass.get_config()
-
- # Copy/re-assign our dictionary values to values understood by the
- # derived _Tunnel classes
- mapping = {
- # this : get_config()
- 'local_ip' : 'local',
- 'remote_ip' : 'remote',
- 'source_interface' : 'dev',
- 'parameters.ip.ttl' : 'ttl',
- 'parameters.ip.tos' : 'tos',
- 'parameters.ip.key' : 'key',
- 'parameters.ipv6.encaplimit' : 'encaplimit'
- }
-
- # Add additional IPv6 options if tunnel is IPv6 aware
- if tunnel['encapsulation'] in ['ipip6', 'ip6ip6', 'ip6gre']:
- mappingv6 = {
- # this : get_config()
- 'parameters.ipv6.encaplimit' : 'encaplimit',
- 'parameters.ipv6.flowlabel' : 'flowlabel',
- 'parameters.ipv6.hoplimit' : 'hoplimit',
- 'parameters.ipv6.tclass' : 'flowlabel'
- }
- mapping.update(mappingv6)
-
- for our_key, their_key in mapping.items():
- if dict_search(our_key, tunnel) and their_key in conf:
- conf[their_key] = dict_search(our_key, tunnel)
-
- if dict_search('parameters.ip.no_pmtu_discovery', tunnel) != None:
- if 'pmtudisc' in conf['raw']:
- conf['raw'].remove('pmtudisc')
- conf['raw'].append('nopmtudisc')
-
- tun = klass(tunnel['ifname'], **conf)
- tun.change_options()
+ tun = TunnelIf(**tunnel)
tun.update(tunnel)
return None
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index 9a6d72772..8e6247a30 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -90,19 +90,8 @@ def apply(vxlan):
v.remove()
if 'deleted' not in vxlan:
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = VXLANIf.get_config()
-
- # Assign VXLAN instance configuration parameters to config dict
- for tmp in ['vni', 'group', 'source_address', 'source_interface', 'remote', 'port']:
- if tmp in vxlan:
- conf[tmp] = vxlan[tmp]
-
# Finally create the new interface
- v = VXLANIf(vxlan['ifname'], **conf)
+ v = VXLANIf(**vxlan)
v.update(vxlan)
return None
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index b25fcd4e0..7b3de6e8a 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -255,17 +255,8 @@ def apply(wifi):
if 'deleted' in wifi:
WiFiIf(interface).remove()
else:
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = WiFiIf.get_config()
-
- # Assign WiFi instance configuration parameters to config dict
- conf['phy'] = wifi['physical_device']
-
# Finally create the new interface
- w = WiFiIf(interface, **conf)
+ w = WiFiIf(**wifi)
w.update(wifi)
# Enable/Disable interface - interface is always placed in
diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py
index dc3cd550c..e2bd6417d 100755
--- a/src/conf_mode/nat66.py
+++ b/src/conf_mode/nat66.py
@@ -79,8 +79,10 @@ def get_config(config=None):
if not conf.exists(base):
nat['helper_functions'] = 'remove'
+ nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_HELPER')
nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT','NAT_CONNTRACK')
+ nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_HELPER')
+ nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK')
nat['deleted'] = ''
return nat
@@ -90,8 +92,10 @@ def get_config(config=None):
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')
- nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT','VYATTA_CT_OUTPUT_HOOK')
+ nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_IGNORE')
+ nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_OUTPUT_HOOK')
else:
nat['helper_functions'] = 'has'
@@ -116,10 +120,10 @@ def verify(nat):
if config['outbound_interface'] not in interfaces():
print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')
- prefix = dict_search('translation.prefix', config)
- if prefix != None:
- if not is_ipv6(prefix):
- raise ConfigError(f'Warning: IPv6 prefix {prefix} is not a valid address prefix')
+ 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')
prefix = dict_search('source.prefix', config)
if prefix != None:
diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py
index d1e551cad..a43eed504 100755
--- a/src/conf_mode/protocols_bfd.py
+++ b/src/conf_mode/protocols_bfd.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
@@ -17,191 +17,97 @@
import os
from sys import exit
-from copy import deepcopy
from vyos.config import Config
+from vyos.configdict import dict_merge
from vyos.template import is_ipv6
-from vyos.template import render
+from vyos.template import render_to_string
from vyos.util import call
from vyos.validate import is_ipv6_link_local
+from vyos.xml import defaults
from vyos import ConfigError
+from vyos import frr
from vyos import airbag
airbag.enable()
-config_file = r'/tmp/bfd.frr'
-
-default_config_data = {
- 'new_peers': [],
- 'old_peers' : []
-}
-
-# get configuration for BFD peer from proposed or effective configuration
-def get_bfd_peer_config(peer, conf_mode="proposed"):
- conf = Config()
- conf.set_level('protocols bfd peer {0}'.format(peer))
-
- bfd_peer = {
- 'remote': peer,
- 'shutdown': False,
- 'src_if': '',
- 'src_addr': '',
- 'multiplier': '3',
- 'rx_interval': '300',
- 'tx_interval': '300',
- 'multihop': False,
- 'echo_interval': '',
- 'echo_mode': False,
- }
-
- # Check if individual peer is disabled
- if conf_mode == "effective" and conf.exists_effective('shutdown'):
- bfd_peer['shutdown'] = True
- if conf_mode == "proposed" and conf.exists('shutdown'):
- bfd_peer['shutdown'] = True
-
- # Check if peer has a local source interface configured
- if conf_mode == "effective" and conf.exists_effective('source interface'):
- bfd_peer['src_if'] = conf.return_effective_value('source interface')
- if conf_mode == "proposed" and conf.exists('source interface'):
- bfd_peer['src_if'] = conf.return_value('source interface')
-
- # Check if peer has a local source address configured - this is mandatory for IPv6
- if conf_mode == "effective" and conf.exists_effective('source address'):
- bfd_peer['src_addr'] = conf.return_effective_value('source address')
- if conf_mode == "proposed" and conf.exists('source address'):
- bfd_peer['src_addr'] = conf.return_value('source address')
-
- # Tell BFD daemon that we should expect packets with TTL less than 254
- # (because it will take more than one hop) and to listen on the multihop
- # port (4784)
- if conf_mode == "effective" and conf.exists_effective('multihop'):
- bfd_peer['multihop'] = True
- if conf_mode == "proposed" and conf.exists('multihop'):
- bfd_peer['multihop'] = True
-
- # Configures the minimum interval that this system is capable of receiving
- # control packets. The default value is 300 milliseconds.
- if conf_mode == "effective" and conf.exists_effective('interval receive'):
- bfd_peer['rx_interval'] = conf.return_effective_value('interval receive')
- if conf_mode == "proposed" and conf.exists('interval receive'):
- bfd_peer['rx_interval'] = conf.return_value('interval receive')
-
- # The minimum transmission interval (less jitter) that this system wants
- # to use to send BFD control packets.
- if conf_mode == "effective" and conf.exists_effective('interval transmit'):
- bfd_peer['tx_interval'] = conf.return_effective_value('interval transmit')
- if conf_mode == "proposed" and conf.exists('interval transmit'):
- bfd_peer['tx_interval'] = conf.return_value('interval transmit')
-
- # Configures the detection multiplier to determine packet loss. The remote
- # transmission interval will be multiplied by this value to determine the
- # connection loss detection timer. The default value is 3.
- if conf_mode == "effective" and conf.exists_effective('interval multiplier'):
- bfd_peer['multiplier'] = conf.return_effective_value('interval multiplier')
- if conf_mode == "proposed" and conf.exists('interval multiplier'):
- bfd_peer['multiplier'] = conf.return_value('interval multiplier')
-
- # Configures the minimal echo receive transmission interval that this system is capable of handling
- if conf_mode == "effective" and conf.exists_effective('interval echo-interval'):
- bfd_peer['echo_interval'] = conf.return_effective_value('interval echo-interval')
- if conf_mode == "proposed" and conf.exists('interval echo-interval'):
- bfd_peer['echo_interval'] = conf.return_value('interval echo-interval')
-
- # Enables or disables the echo transmission mode
- if conf_mode == "effective" and conf.exists_effective('echo-mode'):
- bfd_peer['echo_mode'] = True
- if conf_mode == "proposed" and conf.exists('echo-mode'):
- bfd_peer['echo_mode'] = True
-
- return bfd_peer
-
-def get_config():
- bfd = deepcopy(default_config_data)
- conf = Config()
- if not (conf.exists('protocols bfd') or conf.exists_effective('protocols bfd')):
- return None
+def get_config(config=None):
+ if config:
+ conf = config
else:
- conf.set_level('protocols bfd')
-
- # as we have to use vtysh to talk to FRR we also need to know
- # which peers are gone due to a config removal - thus we read in
- # all peers (active or to delete)
- for peer in conf.list_effective_nodes('peer'):
- bfd['old_peers'].append(get_bfd_peer_config(peer, "effective"))
-
- for peer in conf.list_nodes('peer'):
- bfd['new_peers'].append(get_bfd_peer_config(peer))
-
- # find deleted peers
- set_new_peers = set(conf.list_nodes('peer'))
- set_old_peers = set(conf.list_effective_nodes('peer'))
- bfd['deleted_peers'] = set_old_peers - set_new_peers
+ conf = Config()
+ base = ['protocols', 'bfd']
+ bfd = conf.get_config_dict(base, get_first_key=True)
+
+ # Bail out early if configuration tree does not exist
+ if not conf.exists(base):
+ return bfd
+
+ # We have gathered the dict representation of the CLI, but there are
+ # default options which we need to update into the dictionary retrived.
+ # XXX: T2665: we currently have no nice way for defaults under tag
+ # nodes, thus we load the defaults "by hand"
+ default_values = defaults(base + ['peer'])
+ if 'peer' in bfd:
+ for peer in bfd['peer']:
+ bfd['peer'][peer] = dict_merge(default_values, bfd['peer'][peer])
+
+ if 'profile' in bfd:
+ for profile in bfd['profile']:
+ bfd['profile'][profile] = dict_merge(default_values, bfd['profile'][profile])
return bfd
def verify(bfd):
- if bfd is None:
+ if not bfd:
return None
- # some variables to use later
- conf = Config()
-
- for peer in bfd['new_peers']:
- # IPv6 link local peers require an explicit local address/interface
- if is_ipv6_link_local(peer['remote']):
- if not (peer['src_if'] and peer['src_addr']):
- raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting')
-
- # IPv6 peers require an explicit local address
- if is_ipv6(peer['remote']):
- if not peer['src_addr']:
- raise ConfigError('BFD IPv6 peers require explicit local address setting')
-
- # multihop require source address
- if peer['multihop'] and not peer['src_addr']:
- raise ConfigError('Multihop require source address')
-
- # multihop and echo-mode cannot be used together
- if peer['multihop'] and peer['echo_mode']:
- raise ConfigError('Multihop and echo-mode cannot be used together')
-
- # multihop doesn't accept interface names
- if peer['multihop'] and peer['src_if']:
- raise ConfigError('Multihop and source interface cannot be used together')
-
- # echo interval can be configured only with enabled echo-mode
- if peer['echo_interval'] != '' and not peer['echo_mode']:
- raise ConfigError('echo-interval can be configured only with enabled echo-mode')
-
- # check if we deleted peers are not used in configuration
- if conf.exists('protocols bgp'):
- bgp_as = conf.list_nodes('protocols bgp')[0]
-
- # check BGP neighbors
- for peer in bfd['deleted_peers']:
- if conf.exists('protocols bgp {0} neighbor {1} bfd'.format(bgp_as, peer)):
- raise ConfigError('Cannot delete BFD peer {0}: it is used in BGP configuration'.format(peer))
- if conf.exists('protocols bgp {0} neighbor {1} peer-group'.format(bgp_as, peer)):
- peer_group = conf.return_value('protocols bgp {0} neighbor {1} peer-group'.format(bgp_as, peer))
- if conf.exists('protocols bgp {0} peer-group {1} bfd'.format(bgp_as, peer_group)):
- raise ConfigError('Cannot delete BFD peer {0}: it belongs to BGP peer-group {1} with enabled BFD'.format(peer, peer_group))
+ if 'peer' in bfd:
+ for peer, peer_config in bfd['peer'].items():
+ # IPv6 link local peers require an explicit local address/interface
+ if is_ipv6_link_local(peer):
+ if 'source' not in peer_config or len(peer_config['source'] < 2):
+ raise ConfigError('BFD IPv6 link-local peers require explicit local address and interface setting')
+
+ # IPv6 peers require an explicit local address
+ if is_ipv6(peer):
+ if 'source' not in peer_config or 'address' not in peer_config['source']:
+ raise ConfigError('BFD IPv6 peers require explicit local address setting')
+
+ if 'multihop' in peer_config:
+ # multihop require source address
+ if 'source' not in peer_config or 'address' not in peer_config['source']:
+ raise ConfigError('BFD multihop require source address')
+
+ # multihop and echo-mode cannot be used together
+ if 'echo_mode' in peer_config:
+ raise ConfigError('Multihop and echo-mode cannot be used together')
+
+ # multihop doesn't accept interface names
+ if 'source' in peer_config and 'interface' in peer_config['source']:
+ raise ConfigError('Multihop and source interface cannot be used together')
return None
def generate(bfd):
- if bfd is None:
+ if not bfd:
+ bfd['new_frr_config'] = ''
return None
- render(config_file, 'frr/bfd.frr.tmpl', bfd)
- return None
+ bfd['new_frr_config'] = render_to_string('frr/bfd.frr.tmpl', bfd)
def apply(bfd):
- if bfd is None:
- return None
-
- call("vtysh -d bfdd -f " + config_file)
- if os.path.exists(config_file):
- os.remove(config_file)
+ # Save original configuration prior to starting any commit actions
+ frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration()
+ frr_cfg.modify_section('^bfd', '')
+ frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bfd['new_frr_config'])
+ frr_cfg.commit_configuration()
+
+ # If FRR config is blank, rerun the blank commit x times due to frr-reload
+ # behavior/bug not properly clearing out on one commit.
+ if bfd['new_frr_config'] == '':
+ for a in range(5):
+ frr_cfg.commit_configuration()
return None
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 54352460c..43ca37f9d 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -17,12 +17,15 @@
import os
from sys import exit
+from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.template import is_ip
from vyos.template import render_to_string
from vyos.util import call
from vyos.util import dict_search
+from vyos.validate import is_addr_assigned
from vyos import ConfigError
from vyos import frr
from vyos import airbag
@@ -35,11 +38,24 @@ def get_config(config=None):
conf = config
else:
conf = Config()
- base = ['protocols', 'bgp']
+
+ vrf = None
+ if len(argv) > 1:
+ vrf = argv[1]
+
+ base_path = ['protocols', 'bgp']
+
+ # eqivalent of the C foo ? 'a' : 'b' statement
+ base = vrf and ['vrf', 'name', vrf, 'protocols', 'bgp'] or base_path
bgp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
- # Bail out early if configuration tree does not exist
+ # Assign the name of our VRF context. This MUST be done before the return
+ # statement below, else on deletion we will delete the default instance
+ # instead of the VRF instance.
+ if vrf: bgp.update({'vrf' : vrf})
+
if not conf.exists(base):
+ bgp.update({'deleted' : ''})
return bgp
# We also need some additional information from the config,
@@ -54,15 +70,44 @@ def get_config(config=None):
return bgp
+def verify_remote_as(peer_config, asn_config):
+ if 'remote_as' in peer_config:
+ return peer_config['remote_as']
+
+ if 'peer_group' in peer_config:
+ peer_group_name = peer_config['peer_group']
+ tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', asn_config)
+ if tmp: return tmp
+
+ if 'interface' in peer_config:
+ if 'remote_as' in peer_config['interface']:
+ return peer_config['interface']['remote_as']
+
+ if 'peer_group' in peer_config['interface']:
+ peer_group_name = peer_config['interface']['peer_group']
+ tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', asn_config)
+ if tmp: return tmp
+
+ return None
+
def verify(bgp):
if not bgp:
return None
- # Check if declared more than one ASN
- if len(bgp) > 1:
- raise ConfigError('Only one BGP AS number can be defined!')
+ # FRR bgpd only supports one Autonomous System Number, verify this!
+ asn = 0
+ for key in bgp:
+ if key.isnumeric():
+ asn +=1
+ if asn > 1:
+ raise ConfigError('Only one BGP AS number can be defined!')
for asn, asn_config in bgp.items():
+ # Workaround for https://phabricator.vyos.net/T1711
+ # We also have a vrf, and deleted key now - so we can only veriy "numbers"
+ if not asn.isnumeric():
+ continue
+
# Common verification for both peer-group and neighbor statements
for neighbor in ['neighbor', 'peer_group']:
# bail out early if there is no neighbor or peer-group statement
@@ -75,22 +120,29 @@ def verify(bgp):
# Check if the configure peer-group exists
if 'peer_group' in peer_config:
peer_group = peer_config['peer_group']
- if peer_group not in asn_config['peer_group']:
+ if 'peer_group' not in asn_config or peer_group not in asn_config['peer_group']:
raise ConfigError(f'Specified peer-group "{peer_group}" for '\
f'neighbor "{neighbor}" does not exist!')
- # Some checks can/must only be done on a neighbor and nor a peer-group
+ # ttl-security and ebgp-multihop can't be used in the same configration
+ if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config:
+ raise ConfigError('You can\'t set both ebgp-multihop and ttl-security hops')
+
+ # Check spaces in the password
+ if 'password' in peer_config and ' ' in peer_config['password']:
+ raise ConfigError('You can\'t use spaces in the password')
+
+ # Some checks can/must only be done on a neighbor and not a peer-group
if neighbor == 'neighbor':
# remote-as must be either set explicitly for the neighbor
# or for the entire peer-group
- if 'interface' in peer_config:
- if 'remote_as' not in peer_config['interface']:
- if 'peer_group' not in peer_config['interface'] or 'remote_as' not in asn_config['peer_group'][ peer_config['interface']['peer_group'] ]:
- raise ConfigError('Remote AS must be set for neighbor or peer-group!')
+ if not verify_remote_as(peer_config, asn_config):
+ raise ConfigError(f'Neighbor "{peer}" remote-as must be set!')
- elif 'remote_as' not in peer_config:
- if 'peer_group' not in peer_config or 'remote_as' not in asn_config['peer_group'][ peer_config['peer_group'] ]:
- raise ConfigError('Remote AS must be set for neighbor or peer-group!')
+ # Only checks for ipv4 and ipv6 neighbors
+ # Check if neighbor address is assigned as system interface address
+ if is_ip(peer) and is_addr_assigned(peer):
+ raise ConfigError(f'Can\'t configure local address as neighbor "{peer}"')
for afi in ['ipv4_unicast', 'ipv6_unicast', 'l2vpn_evpn']:
# Bail out early if address family is not configured
@@ -127,10 +179,10 @@ def verify(bgp):
if 'remote_as' in peer_config and asn != peer_config['remote_as']:
raise ConfigError('route-reflector-client only supported for iBGP peers')
else:
- peer_group_as = dict_search(f'peer_group.{peer_group}.remote_as', asn_config)
- if 'peer_group' in peer_config and peer_group_as != None and peer_group_as != asn:
- raise ConfigError('route-reflector-client only supported for iBGP peers')
-
+ if 'peer_group' in peer_config:
+ peer_group_as = dict_search(f'peer_group.{peer_group}.remote_as', asn_config)
+ if peer_group_as != None and peer_group_as != asn:
+ raise ConfigError('route-reflector-client only supported for iBGP peers')
# Throw an error if a peer group is not configured for allow range
for prefix in dict_search('listen.range', asn_config) or []:
@@ -146,7 +198,7 @@ def verify(bgp):
return None
def generate(bgp):
- if not bgp:
+ if not bgp or 'deleted' in bgp:
bgp['new_frr_config'] = ''
return None
@@ -154,6 +206,8 @@ def generate(bgp):
# of the config dict
asn = list(bgp.keys())[0]
bgp[asn]['asn'] = asn
+ if 'vrf' in bgp:
+ bgp[asn]['vrf'] = bgp['vrf']
bgp['new_frr_config'] = render_to_string('frr/bgp.frr.tmpl', bgp[asn])
return None
@@ -162,7 +216,13 @@ def apply(bgp):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section(f'^router bgp \d+$', '')
+
+ if 'vrf' in bgp:
+ vrf = bgp['vrf']
+ frr_cfg.modify_section(f'^router bgp \d+ vrf {vrf}$', '')
+ else:
+ frr_cfg.modify_section('^router bgp \d+$', '')
+
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 2ce0ab530..ef2aeda7f 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -17,14 +17,17 @@
import os
from sys import exit
+from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.configdict import node_changed
from vyos.configverify import verify_route_maps
from vyos.configverify import verify_interface_exists
from vyos.template import render_to_string
from vyos.util import call
from vyos.util import dict_search
+from vyos.util import get_interface_config
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
@@ -38,16 +41,33 @@ def get_config(config=None):
conf = config
else:
conf = Config()
- base = ['protocols', 'ospf']
+
+ vrf = None
+ if len(argv) > 1:
+ vrf = argv[1]
+
+ base_path = ['protocols', 'ospf']
+
+ # eqivalent of the C foo ? 'a' : 'b' statement
+ base = vrf and ['vrf', 'name', vrf, 'protocols', 'ospf'] or base_path
ospf = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+ # Assign the name of our VRF context. This MUST be done before the return
+ # statement below, else on deletion we will delete the default instance
+ # instead of the VRF instance.
+ if vrf: ospf['vrf'] = vrf
+
# Bail out early if configuration tree does not exist
if not conf.exists(base):
+ ospf.update({'deleted' : ''})
return ospf
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
- default_values = defaults(base)
+ # XXX: Note that we can not call defaults(base), as defaults does not work
+ # on an instance of a tag node. As we use the exact same CLI definition for
+ # both the non-vrf and vrf version this is absolutely safe!
+ default_values = defaults(base_path)
# We have to cleanup the default dict, as default values could enable features
# which are not explicitly enabled on the CLI. Example: default-information
@@ -60,7 +80,7 @@ def get_config(config=None):
del default_values['area']['area_type']['nssa']
if 'mpls_te' not in ospf:
del default_values['mpls_te']
- for protocol in ['bgp', 'connected', 'kernel', 'rip', 'static']:
+ for protocol in ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static']:
if dict_search(f'redistribute.{protocol}', ospf) is None:
del default_values['redistribute'][protocol]
# XXX: T2665: we currently have no nice way for defaults under tag nodes,
@@ -99,6 +119,14 @@ def get_config(config=None):
ospf['interface'][interface] = dict_merge(default_values,
ospf['interface'][interface])
+ # As we no re-use this Python handler for both VRF and non VRF instances for
+ # OSPF we need to find out if any interfaces changed so properly adjust
+ # the FRR configuration and not by acctident change interfaces from a
+ # different VRF.
+ interfaces_removed = node_changed(conf, base + ['interface'])
+ if interfaces_removed:
+ ospf['interface_removed'] = list(interfaces_removed)
+
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify()
base = ['policy']
@@ -121,12 +149,22 @@ def verify(ospf):
# time. FRR will only activate the last option set via CLI.
if {'hello_multiplier', 'dead_interval'} <= set(ospf['interface'][interface]):
raise ConfigError(f'Can not use hello-multiplier and dead-interval ' \
- f'concurrently for "{interface}"!')
+ f'concurrently for {interface}!')
+
+ 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/Vyatta
+ # priorities the interface is bound to the VRF after creation of
+ # the VRF itself, and before any routing protocol is configured.
+ vrf = ospf['vrf']
+ tmp = get_interface_config(interface)
+ if 'master' not in tmp or tmp['master'] != vrf:
+ raise ConfigError(f'Interface {interface} is not a member of VRF {vrf}!')
return None
def generate(ospf):
- if not ospf:
+ if not ospf or 'deleted' in ospf:
ospf['new_frr_config'] = ''
return None
@@ -137,8 +175,19 @@ def apply(ospf):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section(r'interface \S+', '')
- frr_cfg.modify_section('^router ospf$', '')
+
+ if 'vrf' in ospf:
+ vrf = ospf['vrf']
+ frr_cfg.modify_section(f'^router ospf vrf {vrf}$', '')
+ else:
+ frr_cfg.modify_section('^router ospf$', '')
+
+ for key in ['interface', 'interface_removed']:
+ if key not in ospf:
+ continue
+ for interface in ospf[key]:
+ frr_cfg.modify_section(f'^interface {interface}$', '')
+
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)
diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py
index 6c3aaf426..6f068b196 100755
--- a/src/conf_mode/protocols_ospfv3.py
+++ b/src/conf_mode/protocols_ospfv3.py
@@ -23,6 +23,7 @@ from vyos.configdict import dict_merge
from vyos.configverify import verify_route_maps
from vyos.template import render_to_string
from vyos.util import call
+from vyos.ifconfig import Interface
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
@@ -57,6 +58,14 @@ def verify(ospfv3):
return None
verify_route_maps(ospfv3)
+
+ if 'interface' in ospfv3:
+ for ifname, if_config in ospfv3['interface'].items():
+ 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}"')
+
return None
def generate(ospfv3):
@@ -71,7 +80,8 @@ def apply(ospfv3):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section('router ospf6', '')
+ frr_cfg.modify_section(r'^interface \S+', '')
+ frr_cfg.modify_section('^router ospf6$', '')
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospfv3['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)
diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py
index 5d101b33e..51b4acfc8 100755
--- a/src/conf_mode/protocols_static.py
+++ b/src/conf_mode/protocols_static.py
@@ -17,6 +17,7 @@
import os
from sys import exit
+from sys import argv
from vyos.config import Config
from vyos.template import render_to_string
@@ -34,8 +35,19 @@ def get_config(config=None):
conf = config
else:
conf = Config()
- base = ['protocols', 'static']
+
+ vrf = None
+ if len(argv) > 1:
+ vrf = argv[1]
+
+ base_path = ['protocols', 'static']
+ # eqivalent of the C foo ? 'a' : 'b' statement
+ base = vrf and ['vrf', 'name', vrf, 'protocols', 'static'] or base_path
static = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+
+ # Assign the name of our VRF context
+ if vrf: static['vrf'] = vrf
+
return static
def verify(static):
@@ -50,8 +62,14 @@ def apply(static):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section(r'^ip route .*', '')
- frr_cfg.modify_section(r'^ipv6 route .*', '')
+
+ if 'vrf' in static:
+ vrf = static['vrf']
+ frr_cfg.modify_section(f'^vrf {vrf}$', '')
+ else:
+ frr_cfg.modify_section(r'^ip route .*', '')
+ frr_cfg.modify_section(r'^ipv6 route .*', '')
+
frr_cfg.add_before(r'(interface .*|line vty)', static['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)
diff --git a/src/conf_mode/protocols_vrf.py b/src/conf_mode/protocols_vrf.py
deleted file mode 100755
index 227e7d5e1..000000000
--- a/src/conf_mode/protocols_vrf.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2021 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-
-from sys import exit
-
-from vyos.config import Config
-from vyos.template import render_to_string
-from vyos.util import call
-from vyos import ConfigError
-from vyos import frr
-from vyos import airbag
-airbag.enable()
-
-frr_daemon = 'staticd'
-
-def get_config(config=None):
- if config:
- conf = config
- else:
- conf = Config()
- base = ['protocols', 'vrf']
- vrf = conf.get_config_dict(base, key_mangling=('-', '_'))
- return vrf
-
-def verify(vrf):
-
- return None
-
-def generate(vrf):
- vrf['new_frr_config'] = render_to_string('frr/vrf.frr.tmpl', vrf)
- return None
-
-def apply(vrf):
- # Save original configuration prior to starting any commit actions
- frr_cfg = frr.FRRConfig()
- frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section(r'vrf \S+', '')
- frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', vrf['new_frr_config'])
- frr_cfg.commit_configuration(frr_daemon)
-
- # If FRR config is blank, rerun the blank commit x times due to frr-reload
- # behavior/bug not properly clearing out on one commit.
- if vrf['new_frr_config'] == '':
- for a in range(5):
- frr_cfg.commit_configuration(frr_daemon)
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- exit(1)
diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py
index 0e5fc75b0..51050e702 100755
--- a/src/conf_mode/service_console-server.py
+++ b/src/conf_mode/service_console-server.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2020 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -17,6 +17,7 @@
import os
from sys import exit
+from psutil import process_iter
from vyos.config import Config
from vyos.configdict import dict_merge
@@ -25,7 +26,8 @@ from vyos.util import call
from vyos.xml import defaults
from vyos import ConfigError
-config_file = r'/run/conserver/conserver.cf'
+config_file = '/run/conserver/conserver.cf'
+dropbear_systemd_file = '/etc/systemd/system/dropbear@{port}.service.d/override.conf'
def get_config(config=None):
if config:
@@ -59,14 +61,19 @@ def verify(proxy):
if not proxy:
return None
+ processes = process_iter(['name', 'cmdline'])
if 'device' in proxy:
- for device in proxy['device']:
- if 'speed' not in proxy['device'][device]:
- raise ConfigError(f'Serial port speed must be defined for "{device}"!')
+ for device, device_config in proxy['device'].items():
+ for process in processes:
+ if 'agetty' in process.name() and device in process.cmdline():
+ raise ConfigError(f'Port "{device}" already provides a '\
+ 'console used by "system console"!')
+
+ if 'speed' not in device_config:
+ raise ConfigError(f'Port "{device}" requires speed to be set!')
- if 'ssh' in proxy['device'][device]:
- if 'port' not in proxy['device'][device]['ssh']:
- raise ConfigError(f'SSH port must be defined for "{device}"!')
+ if 'ssh' in device_config and 'port' not in device_config['ssh']:
+ raise ConfigError(f'Port "{device}" requires SSH port to be set!')
return None
@@ -75,9 +82,22 @@ def generate(proxy):
return None
render(config_file, 'conserver/conserver.conf.tmpl', proxy)
+ if 'device' in proxy:
+ for device, device_config in proxy['device'].items():
+ if 'ssh' not in device_config:
+ continue
+
+ tmp = {
+ 'device' : device,
+ 'port' : device_config['ssh']['port'],
+ }
+ render(dropbear_systemd_file.format(**tmp),
+ 'conserver/dropbear@.service.tmpl', tmp)
+
return None
def apply(proxy):
+ call('systemctl daemon-reload')
call('systemctl stop dropbear@*.service conserver-server.service')
if not proxy:
@@ -88,10 +108,11 @@ def apply(proxy):
call('systemctl restart conserver-server.service')
if 'device' in proxy:
- for device in proxy['device']:
- if 'ssh' in proxy['device'][device]:
- port = proxy['device'][device]['ssh']['port']
- call(f'systemctl restart dropbear@{device}.service')
+ for device, device_config in proxy['device'].items():
+ if 'ssh' not in device_config:
+ continue
+ port = device_config['ssh']['port']
+ call(f'systemctl restart dropbear@{port}.service')
return None
diff --git a/src/conf_mode/service_webproxy.py b/src/conf_mode/service_webproxy.py
index 8dfae348a..cbbd2e0bc 100755
--- a/src/conf_mode/service_webproxy.py
+++ b/src/conf_mode/service_webproxy.py
@@ -123,9 +123,6 @@ def verify(proxy):
ldap_auth = dict_search('authentication.method', proxy) == 'ldap'
for address, config in proxy['listen_address'].items():
- if not is_addr_assigned(address):
- raise ConfigError(
- f'listen-address "{address}" not assigned on any interface!')
if ldap_auth and 'disable_transparent' not in config:
raise ConfigError('Authentication can not be configured when ' \
'proxy is in transparent mode')
diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py
index b17818797..33a546bd3 100755
--- a/src/conf_mode/system_console.py
+++ b/src/conf_mode/system_console.py
@@ -17,9 +17,8 @@
import os
import re
-from fileinput import input as replace_in_file
from vyos.config import Config
-from vyos.util import call
+from vyos.util import call, read_file, write_file
from vyos.template import render
from vyos import ConfigError, airbag
airbag.enable()
@@ -98,15 +97,27 @@ def generate(console):
if not os.path.isfile(grub_config):
return None
- # stdin/stdout are redirected in replace_in_file(), thus print() is fine
+ lines = read_file(grub_config).split('\n')
+
p = re.compile(r'^(.* console=ttyS0),[0-9]+(.*)$')
- for line in replace_in_file(grub_config, inplace=True):
+ write = False
+ newlines = []
+ for line in lines:
if line.startswith('serial --unit'):
- line = f'serial --unit=0 --speed={speed}\n'
+ newline = f'serial --unit=0 --speed={speed}'
elif p.match(line):
- line = '{},{}{}\n'.format(p.search(line)[1], speed, p.search(line)[2])
+ newline = '{},{}{}'.format(p.search(line)[1], speed, p.search(line)[2])
+ else:
+ newline = line
+
+ if newline != line:
+ write = True
+
+ newlines.append(newline)
+ newlines.append('')
- print(line, end='')
+ if write:
+ write_file(grub_config, '\n'.join(newlines))
return None
diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py
index 4510dd3e7..680a80859 100755
--- a/src/conf_mode/vrrp.py
+++ b/src/conf_mode/vrrp.py
@@ -75,6 +75,7 @@ def get_config(config=None):
group["backup_script"] = config.return_value("transition-script backup")
group["fault_script"] = config.return_value("transition-script fault")
group["stop_script"] = config.return_value("transition-script stop")
+ group["script_mode_force"] = config.exists("transition-script mode-force")
if config.exists("no-preempt"):
group["preempt"] = False
@@ -183,6 +184,11 @@ def verify(data):
if isinstance(pa, IPv4Address):
raise ConfigError("VRRP group {0} uses IPv6 but its peer-address is IPv4".format(group["name"]))
+ # Warn the user about the deprecated mode-force option
+ if group['script_mode_force']:
+ print("""Warning: "transition-script mode-force" VRRP option is deprecated and will be removed in VyOS 1.4.""")
+ print("""It's no longer necessary, so you can safely remove it from your config now.""")
+
# Disallow same VRID on multiple interfaces
_groups = sorted(vrrp_groups, key=(lambda x: x["interface"]))
count = len(_groups) - 1
diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper
index d1161e704..fc035766b 100644
--- a/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper
+++ b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper
@@ -1,5 +1,8 @@
# redefine ip command to use FRR when it is available
+# default route distance
+IF_METRIC=${IF_METRIC:-210}
+
# get status of FRR
function frr_alive () {
/usr/lib/frr/watchfrr.sh all_status
@@ -15,11 +18,12 @@ function frr_alive () {
# convert ip route command to vtysh
function iptovtysh () {
# prepare variables for vtysh command
- local VTYSH_DISTANCE="210"
- local VTYSH_TAG="210"
+ local VTYSH_ACTION=$3
local VTYSH_NETADDR=""
local VTYSH_GATEWAY=""
local VTYSH_DEV=""
+ local VTYSH_TAG="210"
+ local VTYSH_DISTANCE=""
# convert default route to 0.0.0.0/0
if [ "$4" == "default" ] ; then
VTYSH_NETADDR="0.0.0.0/0"
@@ -30,26 +34,32 @@ function iptovtysh () {
if [[ ! $VTYSH_NETADDR =~ ^.*/[[:digit:]]+$ ]] ; then
VTYSH_NETADDR="$VTYSH_NETADDR/32"
fi
+ shift 4
# get gateway address
- if [ "$5" == "via" ] ; then
- VTYSH_GATEWAY=$6
+ if [ "$1" == "via" ] ; then
+ VTYSH_GATEWAY=$2
+ shift 2
fi
# get device name
- if [ "$5" == "dev" ]; then
- VTYSH_DEV=$6
- elif [ "$7" == "dev" ]; then
- VTYSH_DEV=$8
+ if [ "$1" == "dev" ]; then
+ VTYSH_DEV=$2
+ shift 2
+ fi
+ # get distance
+ if [ "$1" == "metric" ]; then
+ VTYSH_DISTANCE=$2
+ shift 2
fi
# Add route to VRF routing table
- local VTYSH_VRF_NAME=$(basename /sys/class/net/$VTYSH_DEV/upper_* | sed -e 's/upper_//')
- if [ -n $VTYSH_VRF_NAME ]; then
+ local VTYSH_VRF_NAME=$(/usr/sbin/ip link show dev $VTYSH_DEV | sed -nre '1s/.* master ([^ ]*) .*/\1/p')
+ if /usr/sbin/ip -d link show dev $VTYSH_DEV | grep -q "vrf_slave"; then
VTYSH_VRF="vrf $VTYSH_VRF_NAME"
fi
VTYSH_CMD="ip route $VTYSH_NETADDR $VTYSH_GATEWAY $VTYSH_DEV tag $VTYSH_TAG $VTYSH_DISTANCE $VTYSH_VRF"
# delete route if the command is "del"
- if [ "$3" == "del" ] ; then
+ if [ "$VTYSH_ACTION" == "del" ] ; then
VTYSH_CMD="no $VTYSH_CMD"
fi
logmsg info "Converted vtysh command: \"$VTYSH_CMD\""
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
index b768e1ae5..edb7c7b27 100644
--- a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
@@ -13,6 +13,8 @@ if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then
$hostsd_client --delete-name-servers --tag "dhcp-${interface}"
hostsd_changes=y
+ if_metric="$IF_METRIC"
+
# try to delete default ip route
for router in $old_routers; do
# check if we are bound to a VRF
@@ -21,8 +23,10 @@ if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then
vrf="vrf $vrf_name"
fi
- logmsg info "Deleting default route: via $router dev ${interface} ${vrf}"
- ip -4 route del default via $router dev ${interface} ${vrf}
+ logmsg info "Deleting default route: via $router dev ${interface} ${if_metric:+metric $if_metric} ${vrf}"
+ ip -4 route del default via $router dev ${interface} ${if_metric:+metric $if_metric} ${vrf}
+
+ if_metric=$((if_metric+1))
done
# delete rfc3442 routes
diff --git a/src/migration-scripts/interfaces/19-to-20 b/src/migration-scripts/interfaces/19-to-20
new file mode 100755
index 000000000..e96663e54
--- /dev/null
+++ b/src/migration-scripts/interfaces/19-to-20
@@ -0,0 +1,61 @@
+#!/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 sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ 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()
+
+ config = ConfigTree(config_file)
+
+ for type in ['tunnel', 'l2tpv3']:
+ base = ['interfaces', type]
+ if not config.exists(base):
+ # Nothing to do
+ continue
+
+ for interface in config.list_nodes(base):
+ # Migrate "interface tunnel <tunX> encapsulation gre-bridge" to gretap
+ encap_path = base + [interface, 'encapsulation']
+ if type == 'tunnel' and config.exists(encap_path):
+ tmp = config.return_value(encap_path)
+ if tmp == 'gre-bridge':
+ config.set(encap_path, value='gretap')
+
+ # Migrate "interface tunnel|l2tpv3 <interface> local-ip" to source-address
+ # Migrate "interface tunnel|l2tpv3 <interface> remote-ip" to remote
+ local_ip_path = base + [interface, 'local-ip']
+ if config.exists(local_ip_path):
+ config.rename(local_ip_path, 'source-address')
+
+ remote_ip_path = base + [interface, 'remote-ip']
+ if config.exists(remote_ip_path):
+ config.rename(remote_ip_path, 'remote')
+
+ 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/migration-scripts/nat/4-to-5 b/src/migration-scripts/nat/4-to-5
index dda191719..b791996e2 100755
--- a/src/migration-scripts/nat/4-to-5
+++ b/src/migration-scripts/nat/4-to-5
@@ -36,9 +36,15 @@ if not config.exists(['nat']):
exit(0)
else:
for direction in ['source', 'destination']:
+ # If a node doesn't exist, we obviously have nothing to do.
if not config.exists(['nat', direction]):
continue
+ # However, we also need to handle the case when a 'source' or 'destination' sub-node does exist,
+ # but there are no rules under it.
+ if not config.list_nodes(['nat', direction]):
+ continue
+
for rule in config.list_nodes(['nat', direction, 'rule']):
base = ['nat', direction, 'rule', rule]
diff --git a/src/migration-scripts/nat66/0-to-1 b/src/migration-scripts/nat66/0-to-1
index 74d64c07b..83b421926 100755
--- a/src/migration-scripts/nat66/0-to-1
+++ b/src/migration-scripts/nat66/0-to-1
@@ -49,7 +49,7 @@ def merge_npt(config,base,rule):
if config.exists(base + ['translation','prefix']):
tmp = config.return_value(base + ['translation','prefix'])
- config.set(merge_base + ['translation','prefix'],value=tmp)
+ config.set(merge_base + ['translation','address'],value=tmp)
if not config.exists(['nat', 'nptv6']):
# Nothing to do
diff --git a/src/migration-scripts/quagga/6-to-7 b/src/migration-scripts/quagga/6-to-7
index f7aca0d2b..25cf5eebd 100755
--- a/src/migration-scripts/quagga/6-to-7
+++ b/src/migration-scripts/quagga/6-to-7
@@ -17,14 +17,17 @@
# - T3037, BGP address-family ipv6-unicast capability dynamic does not exist in
# FRR, there is only a base, per neighbor dynamic capability, migrate config
-import sys
+from sys import argv
+from sys import exit
from vyos.configtree import ConfigTree
+from vyos.template import is_ipv4
+from vyos.template import is_ipv6
-if (len(sys.argv) < 2):
+if (len(argv) < 2):
print("Must specify file name!")
- sys.exit(1)
+ exit(1)
-file_name = sys.argv[1]
+file_name = argv[1]
with open(file_name, 'r') as f:
config_file = f.read()
@@ -34,7 +37,7 @@ config = ConfigTree(config_file)
if not config.exists(base):
# Nothing to do
- sys.exit(0)
+ exit(0)
# Check if BGP is actually configured and obtain the ASN
asn_list = config.list_nodes(base)
@@ -55,30 +58,59 @@ if asn_list:
config.delete(send_comm_path)
cap_dynamic = False
+ peer_group = None
for afi in ['ipv4-unicast', 'ipv6-unicast']:
- afi_path = bgp_base + [neighbor_type, neighbor, 'address-family', afi, 'capability', 'dynamic']
- if config.exists(afi_path):
+ afi_path = bgp_base + [neighbor_type, neighbor, 'address-family', afi]
+ # Exit loop early if AFI does not exist
+ if not config.exists(afi_path):
+ continue
+
+ cap_path = afi_path + ['capability', 'dynamic']
+ if config.exists(cap_path):
cap_dynamic = True
- config.delete(afi_path)
+ config.delete(cap_path)
+
+ # We have now successfully migrated the address-family
+ # specific dynamic capability to the neighbor/peer-group
+ # level. If this has been the only option under the
+ # address-family nodes, we can clean them up by checking if
+ # no other nodes are left under that tree and if so, delete
+ # the parent.
+ #
+ # We walk from the most inner node to the most outer one.
+ cleanup = -1
+ while len(config.list_nodes(cap_path[:cleanup])) == 0:
+ config.delete(cap_path[:cleanup])
+ cleanup -= 1
+
+ peer_group_path = afi_path + ['peer-group']
+ if config.exists(peer_group_path):
+ if ((is_ipv4(neighbor) and afi == 'ipv4-unicast') or
+ (is_ipv6(neighbor) and afi == 'ipv6-unicast')):
+ peer_group = config.return_value(peer_group_path)
+
+ config.delete(peer_group_path)
- # We have now successfully migrated the address-family specific
- # dynamic capability to the neighbor/peer-group level. If this
- # has been the only option under the address-family nodes, we
- # can clean them up by checking if no other nodes are left under
- # that tree and if so, delete the parent.
+ # We have now successfully migrated the address-family
+ # specific peer-group to the neighbor level. If this has
+ # been the only option under the address-family nodes, we
+ # can clean them up by checking if no other nodes are left
+ # under that tree and if so, delete the parent.
#
# We walk from the most inner node to the most outer one.
cleanup = -1
- while len(config.list_nodes(afi_path[:cleanup])) == 0:
- config.delete(afi_path[:cleanup])
+ while len(config.list_nodes(peer_group_path[:cleanup])) == 0:
+ config.delete(peer_group_path[:cleanup])
cleanup -= 1
if cap_dynamic:
config.set(bgp_base + [neighbor_type, neighbor, 'capability', 'dynamic'])
+ if peer_group:
+ config.set(bgp_base + [neighbor_type, neighbor, 'peer-group'], value=peer_group)
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))
- sys.exit(1)
+ exit(1)
diff --git a/src/migration-scripts/quagga/8-to-9 b/src/migration-scripts/quagga/8-to-9
new file mode 100755
index 000000000..15c44924f
--- /dev/null
+++ b/src/migration-scripts/quagga/8-to-9
@@ -0,0 +1,61 @@
+#!/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/>.
+
+# - T3391: Migrate "maximum-paths" setting from "protocols bgp asn maximum-paths"
+# under the IPv4 address-family tree. Reason is we currently have no way in
+# configuring this for IPv6 address-family. This mimics the FRR configuration.
+
+from sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 2):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['protocols', 'bgp']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+# Check if BGP is actually configured and obtain the ASN
+asn_list = config.list_nodes(base)
+if asn_list:
+ # There's always just one BGP node, if any
+ bgp_base = base + [asn_list[0]]
+
+ maximum_paths = bgp_base + ['maximum-paths']
+ if config.exists(maximum_paths):
+ for bgp_type in ['ebgp', 'ibgp']:
+ if config.exists(maximum_paths + [bgp_type]):
+ new_base = bgp_base + ['address-family', 'ipv4-unicast', 'maximum-paths']
+ config.set(new_base)
+ config.copy(maximum_paths + [bgp_type], new_base + [bgp_type])
+ config.delete(maximum_paths)
+
+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/migration-scripts/vrf/1-to-2 b/src/migration-scripts/vrf/1-to-2
new file mode 100755
index 000000000..20128e957
--- /dev/null
+++ b/src/migration-scripts/vrf/1-to-2
@@ -0,0 +1,61 @@
+#!/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/>.
+
+# - T3344: migrate routing options from "protocols vrf" to "vrf <name> protocols"
+
+from sys import argv
+from sys import exit
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 2):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['protocols', 'vrf']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+vrf_base = ['vrf', 'name']
+config.set(vrf_base)
+config.set_tag(vrf_base)
+
+# Copy all existing static routes to the new base node under "vrf name <name> protocols static"
+for vrf in config.list_nodes(base):
+ static_base = base + [vrf, 'static']
+ if not config.exists(static_base):
+ continue
+
+ new_static_base = vrf_base + [vrf, 'protocols']
+ config.set(new_static_base)
+ config.copy(static_base, new_static_base + ['static'])
+
+# Now delete the old configuration
+config.delete(base)
+
+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/ppp-server-ctrl.py b/src/op_mode/ppp-server-ctrl.py
index 171107b4a..8a4e846b2 100755
--- a/src/op_mode/ppp-server-ctrl.py
+++ b/src/op_mode/ppp-server-ctrl.py
@@ -59,7 +59,10 @@ def main():
output, err = popen(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][args.proto]) + args.action + ses_pattern, stderr=DEVNULL, decode='utf-8')
if not err:
- print(output)
+ try:
+ print(output)
+ except BrokenPipeError:
+ sys.exit(0)
else:
print("{} server is not running".format(args.proto))
diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py
index 256c86d2a..39e5dc7ac 100755
--- a/src/op_mode/show_interfaces.py
+++ b/src/op_mode/show_interfaces.py
@@ -30,7 +30,7 @@ from vyos.util import cmd
# interfaces = Sections.reserved()
-interfaces = ['eno', 'ens', 'enp', 'enx', 'eth', 'vmnet', 'lo', 'tun', 'wan', 'pppoe', 'pppoa', 'adsl']
+interfaces = ['eno', 'ens', 'enp', 'enx', 'eth', 'vmnet', 'lo', 'tun', 'wan', 'pppoe']
glob_ifnames = '/sys/class/net/({})*'.format('|'.join(interfaces))
@@ -177,7 +177,7 @@ def run_show_intf(ifnames, iftypes, vif, vrrp):
out = cmd(f'ip addr show {interface.ifname}')
out = re.sub(f'^\d+:\s+','',out)
- if re.search("link/tunnel6", out):
+ if re.search('link/tunnel6', out):
tunnel = cmd(f'ip -6 tun show {interface.ifname}')
# tun0: ip/ipv6 remote ::2 local ::1 encaplimit 4 hoplimit 64 tclass inherit flowlabel inherit (flowinfo 0x00000000)
tunnel = re.sub('.*encap', 'encap', tunnel)
diff --git a/src/op_mode/show_nat66_rules.py b/src/op_mode/show_nat66_rules.py
new file mode 100755
index 000000000..cbab2d03b
--- /dev/null
+++ b/src/op_mode/show_nat66_rules.py
@@ -0,0 +1,74 @@
+#!/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 jmespath
+import json
+
+from argparse import ArgumentParser
+from jinja2 import Template
+from sys import exit
+from vyos.util import cmd
+from vyos.util import dict_search
+
+parser = ArgumentParser()
+group = parser.add_mutually_exclusive_group()
+group.add_argument("--source", help="Show statistics for configured source NAT rules", action="store_true")
+group.add_argument("--destination", help="Show statistics for configured destination NAT rules", action="store_true")
+args = parser.parse_args()
+
+if args.source or args.destination:
+ tmp = cmd('sudo nft -j list table ip6 nat')
+ tmp = json.loads(tmp)
+
+ format_nat66_rule = '%-10s %-50s %-50s %-10s'
+ print(format_nat66_rule % ("Rule", "Source" if args.source else "Destination", "Translation", "Outbound Interface" if args.source else "Inbound Interface"))
+ print(format_nat66_rule % ("----", "------" if args.source else "-----------", "-----------", "------------------" if args.source else "-----------------"))
+
+ data_json = jmespath.search('nftables[?rule].rule[?chain]', tmp)
+ for idx in range(0, len(data_json)):
+ data = data_json[idx]
+ comment = data['comment']
+ chain = data['chain']
+ if not (args.source and chain == 'POSTROUTING') or (not args.source and chain == 'PREROUTING'):
+ exit(0)
+ interface = dict_search('match.right', data['expr'][0])
+ srcdest = dict_search('match.right.prefix.addr', data['expr'][2])
+ if srcdest:
+ addr_tmp = dict_search('match.right.prefix.len', data['expr'][2])
+ if addr_tmp:
+ srcdest = srcdest + '/' + str(addr_tmp)
+ else:
+ srcdest = dict_search('match.right', data['expr'][2])
+ tran_addr = dict_search('snat.addr.prefix.addr' if args.source else 'dnat.addr.prefix.addr', data['expr'][3])
+ if tran_addr:
+ addr_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3])
+ if addr_tmp:
+ srcdest = srcdest + '/' + str(addr_tmp)
+ else:
+ if 'masquerade' in data['expr'][3]:
+ tran_addr = 'masquerade'
+ elif 'log' in data['expr'][3]:
+ continue
+ else:
+ tran_addr = dict_search('snat.addr' if args.source else 'dnat.addr', data['expr'][3])
+
+ print(format_nat66_rule % (comment, srcdest, tran_addr, interface))
+
+ exit(0)
+else:
+ parser.print_help()
+ exit(1)
+
diff --git a/src/op_mode/show_nat66_statistics.py b/src/op_mode/show_nat66_statistics.py
new file mode 100755
index 000000000..0f0b05978
--- /dev/null
+++ b/src/op_mode/show_nat66_statistics.py
@@ -0,0 +1,63 @@
+#!/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 jmespath
+import json
+
+from argparse import ArgumentParser
+from jinja2 import Template
+from sys import exit
+from vyos.util import cmd
+
+OUT_TMPL_SRC="""
+rule pkts bytes interface
+---- ---- ----- ---------
+{% for r in output %}
+{% if r.comment %}
+{% set packets = r.counter.packets %}
+{% set bytes = r.counter.bytes %}
+{% set interface = r.interface %}
+{# remove rule comment prefix #}
+{% set comment = r.comment | replace('SRC-NAT-', '') | replace('DST-NAT-', '') | replace(' tcp_udp', '') %}
+{{ "%-4s" | format(comment) }} {{ "%9s" | format(packets) }} {{ "%12s" | format(bytes) }} {{ interface }}
+{% endif %}
+{% endfor %}
+"""
+
+parser = ArgumentParser()
+group = parser.add_mutually_exclusive_group()
+group.add_argument("--source", help="Show statistics for configured source NAT rules", action="store_true")
+group.add_argument("--destination", help="Show statistics for configured destination NAT rules", action="store_true")
+args = parser.parse_args()
+
+if args.source or args.destination:
+ tmp = cmd('sudo nft -j list table ip6 nat')
+ tmp = json.loads(tmp)
+
+ source = r"nftables[?rule.chain=='POSTROUTING'].rule.{chain: chain, handle: handle, comment: comment, counter: expr[].counter | [0], interface: expr[].match.right | [0] }"
+ destination = r"nftables[?rule.chain=='PREROUTING'].rule.{chain: chain, handle: handle, comment: comment, counter: expr[].counter | [0], interface: expr[].match.right | [0] }"
+ data = {
+ 'output' : jmespath.search(source if args.source else destination, tmp),
+ 'direction' : 'source' if args.source else 'destination'
+ }
+
+ tmpl = Template(OUT_TMPL_SRC, lstrip_blocks=True)
+ print(tmpl.render(data))
+ exit(0)
+else:
+ parser.print_help()
+ exit(1)
+
diff --git a/src/op_mode/show_nat66_translations.py b/src/op_mode/show_nat66_translations.py
new file mode 100755
index 000000000..045d64065
--- /dev/null
+++ b/src/op_mode/show_nat66_translations.py
@@ -0,0 +1,204 @@
+#!/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/>.
+
+'''
+show nat translations
+'''
+
+import os
+import sys
+import ipaddress
+import argparse
+import xmltodict
+
+from vyos.util import popen
+from vyos.util import DEVNULL
+
+conntrack = '/usr/sbin/conntrack'
+
+verbose_format = "%-20s %-18s %-20s %-18s"
+normal_format = "%-20s %-20s %-4s %-8s %s"
+
+
+def headers(verbose, pipe):
+ if verbose:
+ return verbose_format % ('Pre-NAT src', 'Pre-NAT dst', 'Post-NAT src', 'Post-NAT dst')
+ return normal_format % ('Pre-NAT', 'Post-NAT', 'Prot', 'Timeout', 'Type' if pipe else '')
+
+
+def command(srcdest, proto, ipaddr):
+ command = f'{conntrack} -o xml -L -f ipv6'
+
+ if proto:
+ command += f' -p {proto}'
+
+ if srcdest == 'source':
+ command += ' -n'
+ if ipaddr:
+ command += f' --orig-src {ipaddr}'
+ if srcdest == 'destination':
+ command += ' -g'
+ if ipaddr:
+ command += f' --orig-dst {ipaddr}'
+
+ return command
+
+
+def run(command):
+ xml, code = popen(command,stderr=DEVNULL)
+ if code:
+ sys.exit('conntrack failed')
+ return xml
+
+
+def content(xmlfile):
+ xml = ''
+ with open(xmlfile,'r') as r:
+ xml += r.read()
+ return xml
+
+
+def pipe():
+ xml = ''
+ while True:
+ line = sys.stdin.readline()
+ xml += line
+ if '</conntrack>' in line:
+ break
+
+ sys.stdin = open('/dev/tty')
+ return xml
+
+
+def process(data, stats, protocol, pipe, verbose, flowtype=''):
+ if not data:
+ return
+
+ parsed = xmltodict.parse(data)
+
+ print(headers(verbose, pipe))
+
+ # to help the linter to detect typos
+ ORIGINAL = 'original'
+ REPLY = 'reply'
+ INDEPENDANT = 'independent'
+ SPORT = 'sport'
+ DPORT = 'dport'
+ SRC = 'src'
+ DST = 'dst'
+
+ for rule in parsed['conntrack']['flow']:
+ src, dst, sport, dport, proto = {}, {}, {}, {}, {}
+ packet_count, byte_count = {}, {}
+ timeout, use = 0, 0
+
+ rule_type = rule.get('type', '')
+
+ for meta in rule['meta']:
+ # print(meta)
+ direction = meta['@direction']
+
+ if direction in (ORIGINAL, REPLY):
+ if 'layer3' in meta:
+ l3 = meta['layer3']
+ src[direction] = l3[SRC]
+ dst[direction] = l3[DST]
+
+ if 'layer4' in meta:
+ l4 = meta['layer4']
+ sp = l4.get(SPORT, '')
+ dp = l4.get(DPORT, '')
+ if sp:
+ sport[direction] = sp
+ if dp:
+ dport[direction] = dp
+ proto[direction] = l4.get('@protoname','')
+
+ if stats and 'counters' in meta:
+ packet_count[direction] = meta['packets']
+ byte_count[direction] = meta['bytes']
+ continue
+
+ if direction == INDEPENDANT:
+ timeout = meta['timeout']
+ use = meta['use']
+ continue
+
+ in_src = '%s:%s' % (src[ORIGINAL], sport[ORIGINAL]) if ORIGINAL in sport else src[ORIGINAL]
+ in_dst = '%s:%s' % (dst[ORIGINAL], dport[ORIGINAL]) if ORIGINAL in dport else dst[ORIGINAL]
+
+ # inverted the the perl code !!?
+ out_dst = '%s:%s' % (dst[REPLY], dport[REPLY]) if REPLY in dport else dst[REPLY]
+ out_src = '%s:%s' % (src[REPLY], sport[REPLY]) if REPLY in sport else src[REPLY]
+
+ if flowtype == 'source':
+ v = ORIGINAL in sport and REPLY in dport
+ f = '%s:%s' % (src[ORIGINAL], sport[ORIGINAL]) if v else src[ORIGINAL]
+ t = '%s:%s' % (dst[REPLY], dport[REPLY]) if v else dst[REPLY]
+ else:
+ v = ORIGINAL in dport and REPLY in sport
+ f = '%s:%s' % (dst[ORIGINAL], dport[ORIGINAL]) if v else dst[ORIGINAL]
+ t = '%s:%s' % (src[REPLY], sport[REPLY]) if v else src[REPLY]
+
+ # Thomas: I do not believe proto should be an option
+ p = proto.get('original', '')
+ if protocol and p != protocol:
+ continue
+
+ if verbose:
+ msg = verbose_format % (in_src, in_dst, out_dst, out_src)
+ p = f'{p}: ' if p else ''
+ msg += f'\n {p}{f} ==> {t}'
+ msg += f' timeout: {timeout}' if timeout else ''
+ msg += f' use: {use} ' if use else ''
+ msg += f' type: {rule_type}' if rule_type else ''
+ print(msg)
+ else:
+ print(normal_format % (f, t, p, timeout, rule_type if rule_type else ''))
+
+ if stats:
+ for direction in ('original', 'reply'):
+ if direction in packet_count:
+ print(' %-8s: packets %s, bytes %s' % direction, packet_count[direction], byte_count[direction])
+
+
+def main():
+ parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
+ parser.add_argument('--verbose', help='provide more details about the flows', action='store_true')
+ parser.add_argument('--proto', help='filter by protocol', default='', type=str)
+ parser.add_argument('--file', help='read the conntrack xml from a file', type=str)
+ parser.add_argument('--stats', help='add usage statistics', action='store_true')
+ parser.add_argument('--type', help='NAT type (source, destination)', required=True, type=str)
+ parser.add_argument('--ipaddr', help='source ip address to filter on', type=ipaddress.ip_address)
+ parser.add_argument('--pipe', help='read conntrack xml data from stdin', action='store_true')
+
+ arg = parser.parse_args()
+
+ if arg.type not in ('source', 'destination'):
+ sys.exit('Unknown NAT type!')
+
+ if arg.pipe:
+ process(pipe(), arg.stats, arg.proto, arg.pipe, arg.verbose, arg.type)
+ elif arg.file:
+ process(content(arg.file), arg.stats, arg.proto, arg.pipe, arg.verbose, arg.type)
+ else:
+ try:
+ process(run(command(arg.type, arg.proto, arg.ipaddr)), arg.stats, arg.proto, arg.pipe, arg.verbose, arg.type)
+ except:
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/src/op_mode/show_nat_rules.py b/src/op_mode/show_nat_rules.py
new file mode 100755
index 000000000..0ddb7ddd4
--- /dev/null
+++ b/src/op_mode/show_nat_rules.py
@@ -0,0 +1,74 @@
+#!/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 jmespath
+import json
+
+from argparse import ArgumentParser
+from jinja2 import Template
+from sys import exit
+from vyos.util import cmd
+from vyos.util import dict_search
+
+parser = ArgumentParser()
+group = parser.add_mutually_exclusive_group()
+group.add_argument("--source", help="Show statistics for configured source NAT rules", action="store_true")
+group.add_argument("--destination", help="Show statistics for configured destination NAT rules", action="store_true")
+args = parser.parse_args()
+
+if args.source or args.destination:
+ tmp = cmd('sudo nft -j list table ip nat')
+ tmp = json.loads(tmp)
+
+ format_nat66_rule = '%-10s %-50s %-50s %-10s'
+ print(format_nat66_rule % ("Rule", "Source" if args.source else "Destination", "Translation", "Outbound Interface" if args.source else "Inbound Interface"))
+ print(format_nat66_rule % ("----", "------" if args.source else "-----------", "-----------", "------------------" if args.source else "-----------------"))
+
+ data_json = jmespath.search('nftables[?rule].rule[?chain]', tmp)
+ for idx in range(0, len(data_json)):
+ data = data_json[idx]
+ comment = data['comment']
+ chain = data['chain']
+ if not (args.source and chain == 'POSTROUTING') or (not args.source and chain == 'PREROUTING'):
+ exit(0)
+ interface = dict_search('match.right', data['expr'][0])
+ srcdest = dict_search('match.right.prefix.addr', data['expr'][1])
+ if srcdest:
+ addr_tmp = dict_search('match.right.prefix.len', data['expr'][1])
+ if addr_tmp:
+ srcdest = srcdest + '/' + str(addr_tmp)
+ else:
+ srcdest = dict_search('match.right', data['expr'][1])
+ tran_addr = dict_search('snat.addr.prefix.addr' if args.source else 'dnat.addr.prefix.addr', data['expr'][3])
+ if tran_addr:
+ addr_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3])
+ if addr_tmp:
+ srcdest = srcdest + '/' + str(addr_tmp)
+ else:
+ if 'masquerade' in data['expr'][3]:
+ tran_addr = 'masquerade'
+ elif 'log' in data['expr'][3]:
+ continue
+ else:
+ tran_addr = dict_search('snat.addr' if args.source else 'dnat.addr', data['expr'][3])
+
+ print(format_nat66_rule % (comment, srcdest, tran_addr, interface))
+
+ exit(0)
+else:
+ parser.print_help()
+ exit(1)
+
diff --git a/src/op_mode/show_nat_statistics.py b/src/op_mode/show_nat_statistics.py
index 482993d06..c568c8305 100755
--- a/src/op_mode/show_nat_statistics.py
+++ b/src/op_mode/show_nat_statistics.py
@@ -44,7 +44,7 @@ group.add_argument("--destination", help="Show statistics for configured destina
args = parser.parse_args()
if args.source or args.destination:
- tmp = cmd('sudo nft -j list table nat')
+ tmp = cmd('sudo nft -j list table ip nat')
tmp = json.loads(tmp)
source = r"nftables[?rule.chain=='POSTROUTING'].rule.{chain: chain, handle: handle, comment: comment, counter: expr[].counter | [0], interface: expr[].match.right | [0] }"
diff --git a/src/op_mode/vtysh_wrapper.sh b/src/op_mode/vtysh_wrapper.sh
new file mode 100755
index 000000000..47d88330b
--- /dev/null
+++ b/src/op_mode/vtysh_wrapper.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+declare -a tmp
+tmp=$@
+vtysh -c "$tmp"
diff --git a/src/services/vyos-configd b/src/services/vyos-configd
index 5b1ab1f1f..1e60e53df 100755
--- a/src/services/vyos-configd
+++ b/src/services/vyos-configd
@@ -25,6 +25,7 @@ import logging
import signal
import importlib.util
import zmq
+from contextlib import redirect_stdout, redirect_stderr
from vyos.defaults import directories
from vyos.configsource import ConfigSourceString, ConfigSourceError
@@ -33,6 +34,8 @@ from vyos import ConfigError
CFG_GROUP = 'vyattacfg'
+script_stdout_log = '/tmp/vyos-configd-script-stdout'
+
debug = True
logger = logging.getLogger(__name__)
@@ -59,7 +62,8 @@ configd_env_unset_file = os.path.join(directories['data'], 'vyos-configd-env-uns
# sourced on entering config session
configd_env_file = '/etc/default/vyos-configd-env'
-session_tty = None
+session_out = None
+session_mode = None
def key_name_from_file_name(f):
return os.path.splitext(f)[0]
@@ -104,33 +108,30 @@ conf_mode_scripts = dict(zip(imports, modules))
exclude_set = {key_name_from_file_name(f) for f in filenames if f not in include}
include_set = {key_name_from_file_name(f) for f in filenames if f in include}
-def explicit_print(t, m):
- try:
- with open(t, 'w') as f:
- f.write(m)
- f.write("\n")
- f.flush()
- except Exception:
- pass
def run_script(script, config) -> int:
config.set_level([])
try:
- c = script.get_config(config)
- script.verify(c)
- script.generate(c)
- script.apply(c)
+ with open(session_out, session_mode) as f, redirect_stdout(f):
+ with redirect_stderr(f):
+ c = script.get_config(config)
+ script.verify(c)
+ script.generate(c)
+ script.apply(c)
except ConfigError as e:
logger.critical(e)
- explicit_print(session_tty, str(e))
+ with open(session_out, session_mode) as f, redirect_stdout(f):
+ print(f"{e}\n")
return R_ERROR_COMMIT
- except Exception:
+ except Exception as e:
+ logger.critical(e)
return R_ERROR_DAEMON
return R_SUCCESS
def initialization(socket):
- global session_tty
+ global session_out
+ global session_mode
# Reset config strings:
active_string = ''
session_string = ''
@@ -158,9 +159,15 @@ def initialization(socket):
logger.debug(f"config session pid is {pid_string}")
try:
- session_tty = os.readlink(f"/proc/{pid_string}/fd/1")
+ session_out = os.readlink(f"/proc/{pid_string}/fd/1")
+ session_mode = 'w'
except FileNotFoundError:
- session_tty = None
+ session_out = None
+
+ # if not a 'live' session, for example on boot, write to file
+ if not session_out or '/dev/pts' not in session_out:
+ session_out = script_stdout_log
+ session_mode = 'a'
try:
configsource = ConfigSourceString(running_config_text=active_string,
diff --git a/src/system/on-dhcp-event.sh b/src/system/on-dhcp-event.sh
index a062dc810..49e53d7e1 100755
--- a/src/system/on-dhcp-event.sh
+++ b/src/system/on-dhcp-event.sh
@@ -21,21 +21,20 @@ client_mac=$4
domain=$5
hostsd_client="/usr/bin/vyos-hostsd-client"
-if [ -z "$client_name" ]; then
- logger -s -t on-dhcp-event "Client name was empty, using MAC \"$client_mac\" instead"
- client_name=$(echo "client-"$client_mac | tr : -)
-fi
-
-if [ "$domain" == "..YYZ!" ]; then
- client_fqdn_name=$client_name
- client_search_expr=$client_name
-else
- client_fqdn_name=$client_name.$domain
- client_search_expr="$client_name\\.$domain"
-fi
-
case "$action" in
commit) # add mapping for new lease
+ if [ -z "$client_name" ]; then
+ logger -s -t on-dhcp-event "Client name was empty, using MAC \"$client_mac\" instead"
+ client_name=$(echo "client-"$client_mac | tr : -)
+ fi
+
+ if [ "$domain" == "..YYZ!" ]; then
+ client_fqdn_name=$client_name
+ client_search_expr=$client_name
+ else
+ client_fqdn_name=$client_name.$domain
+ client_search_expr="$client_name\\.$domain"
+ fi
$hostsd_client --add-hosts "$client_fqdn_name,$client_ip" --tag "dhcp-server-$client_ip" --apply
exit 0
;;
diff --git a/src/systemd/dropbear@.service b/src/systemd/dropbear@.service
index a3fde5708..acf926af9 100644
--- a/src/systemd/dropbear@.service
+++ b/src/systemd/dropbear@.service
@@ -8,9 +8,8 @@ StartLimitIntervalSec=0
[Service]
Type=forking
-ExecStartPre=/usr/bin/bash -c '/usr/bin/systemctl set-environment PORT=$(cli-shell-api returnActiveValue service console-server device "%I" ssh port)'
-ExecStart=-/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -c "/usr/bin/console %I" -P /run/conserver/dropbear.%I.pid -p ${PORT}
-PIDFile=/run/conserver/dropbear.%I.pid
+ExecStart=/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -P /run/dropbear/dropbear.%I.pid -p %I
+PIDFile=/run/dropbear/dropbear.%I.pid
KillMode=process
Restart=always
RestartSec=10
diff --git a/src/tests/test_util.py b/src/tests/test_util.py
index f7405cbde..22bc085c5 100644
--- a/src/tests/test_util.py
+++ b/src/tests/test_util.py
@@ -17,11 +17,7 @@
from unittest import TestCase
from vyos.util import mangle_dict_keys
-
class TestVyOSUtil(TestCase):
- def setUp(self):
- pass
-
def test_key_mangline(self):
data = {"foo-bar": {"baz-quux": None}}
expected_data = {"foo_bar": {"baz_quux": None}}
diff --git a/src/validators/fqdn b/src/validators/fqdn
index 66276c093..a4027e4ca 100755
--- a/src/validators/fqdn
+++ b/src/validators/fqdn
@@ -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
@@ -17,8 +17,7 @@
import re
import sys
-# pattern copied from: https://www.regextester.com/103452
-pattern = "(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)"
+pattern = '[A-Za-z0-9][-.A-Za-z0-9]*'
if __name__ == '__main__':
if len(sys.argv) != 2:
diff --git a/src/validators/interface-name b/src/validators/interface-name
index 32cd42fbd..72e9fd54a 100755
--- a/src/validators/interface-name
+++ b/src/validators/interface-name
@@ -17,7 +17,7 @@
import re
import sys
-pattern = '^(br|bond|dum|en|eth|gnv|peth|pppoe|tun|vti|vtun|vxlan|wg|wlan)[0-9]+|lo$'
+pattern = '^(bond|br|dum|en|ersp|eth|gnv|lan|l2tp|l2tpeth|macsec|peth|ppp|pppoe|pptp|sstp|tun|vti|vtun|vxlan|wg|wlan|wlm)[0-9]+(.\d+)?|lo$'
if __name__ == '__main__':
if len(sys.argv) != 2: