1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
{# Common macro for recurroiing options for a static route #}
{% macro route_options(route, interface_or_next_hop, config, table) %}
{# j2lint: disable=jinja-statements-delimeter #}
{% set ip_route = route ~ ' ' ~ interface_or_next_hop %}
{% if config.interface is vyos_defined %}
{% set ip_route = ip_route ~ ' ' ~ config.interface %}
{% endif %}
{% if config.tag is vyos_defined %}
{% set ip_route = ip_route ~ ' tag ' ~ config.tag %}
{% endif %}
{% if config.distance is vyos_defined %}
{% set ip_route = ip_route ~ ' ' ~ config.distance %}
{% endif %}
{% if config.bfd is vyos_defined %}
{% set ip_route = ip_route ~ ' bfd' %}
{% if config.bfd.multi_hop is vyos_defined %}
{% set ip_route = ip_route ~ ' multi-hop' %}
{% if config.bfd.multi_hop.source_address is vyos_defined %}
{% set ip_route = ip_route ~ ' source ' ~ config.bfd.multi_hop.source_address %}
{% endif %}
{% endif %}
{% if config.bfd.profile is vyos_defined %}
{% set ip_route = ip_route ~ ' profile ' ~ config.bfd.profile %}
{% endif %}
{% endif %}
{% if config.vrf is vyos_defined %}
{% set ip_route = ip_route ~ ' nexthop-vrf ' ~ config.vrf %}
{% endif %}
{% if config.segments is vyos_defined %}
{# Segments used in/for SRv6 #}
{% set ip_route = ip_route ~ ' segments ' ~ config.segments %}
{% endif %}
{# Routing table to configure #}
{% if table is vyos_defined %}
{% set ip_route = ip_route ~ ' table ' ~ table %}
{% endif %}
{{ ip_route }}
{%- endmacro -%}
{# Build static IPv4/IPv6 route #}
{% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %}
{% set route = ip_ipv6 ~ 'route ' ~ prefix %}
{% if prefix_config.interface is vyos_defined %}
{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
{{ route_options(route, interface, interface_config, table) }}
{% endfor %}
{% endif %}
{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %}
{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %}
{{ route_options(route, next_hop, next_hop_config, table) }}
{% endfor %}
{% endif %}
{% if prefix_config.dhcp_interface is vyos_defined %}
{% for dhcp_interface in prefix_config.dhcp_interface %}
{% set next_hop = dhcp_interface | get_dhcp_router %}
{% if next_hop is vyos_defined %}
{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }}
{% endif %}
{% endfor %}
{% endif %}
{% if prefix_config.blackhole is vyos_defined %}
{{ route_options(route, 'blackhole', prefix_config.blackhole, table) }}
{% elif prefix_config.reject is vyos_defined %}
{{ route_options(route, 'reject', prefix_config.reject, table) }}
{% endif %}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endmacro -%}
!
{% set ip_prefix = 'ip ' %}
{% set ipv6_prefix = 'ipv6 ' %}
{% if vrf is vyos_defined %}
{# 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 vyos_defined %}
{% for prefix, prefix_config in route.items() %}
{{ static_routes(ip_prefix, prefix, prefix_config) }}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endfor %}
{% endif %}
{# IPv4 default routes from DHCP interfaces #}
{% if dhcp is vyos_defined %}
{% for interface, interface_config in dhcp.items() if interface_config.dhcp_options.no_default_route is not vyos_defined %}
{% set next_hop = interface | get_dhcp_router %}
{% if next_hop is vyos_defined %}
{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 {{ interface_config.dhcp_options.default_route_distance if interface_config.dhcp_options.default_route_distance is vyos_defined }}
{% endif %}
{% endfor %}
{% endif %}
{# IPv4 default routes from PPPoE interfaces #}
{% if pppoe is vyos_defined %}
{% for interface, interface_config in pppoe.items() if interface_config.no_default_route is not vyos_defined %}
{{ ip_prefix }} route 0.0.0.0/0 {{ interface }} tag 210 {{ interface_config.default_route_distance if interface_config.default_route_distance is vyos_defined }}
{%- endfor %}
{% endif %}
{# IPv6 routing #}
{% if route6 is vyos_defined %}
{% for prefix, prefix_config in route6.items() %}
{{ static_routes(ipv6_prefix, prefix, prefix_config) }}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endfor %}
{% endif %}
{% if vrf is vyos_defined %}
exit-vrf
{% endif %}
!
{# Policy route tables #}
{% if table is vyos_defined %}
{% for table_id, table_config in table.items() %}
{% if table_config.route is vyos_defined %}
{% for prefix, prefix_config in table_config.route.items() %}
{{ static_routes('ip ', prefix, prefix_config, table_id) }}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endfor %}
{% endif %}
!
{% if table_config.route6 is vyos_defined %}
{% for prefix, prefix_config in table_config.route6.items() %}
{{ static_routes('ipv6 ', prefix, prefix_config, table_id) }}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endfor %}
{% endif %}
!
{% endfor %}
{% endif %}
!
{# Multicast route #}
{% if mroute is vyos_defined %}
{% set ip_prefix = 'ip m' %}
{# IPv4 multicast routing #}
{% for prefix, prefix_config in mroute.items() %}
{{ static_routes(ip_prefix, prefix, prefix_config) }}
{# j2lint: disable=jinja-statements-delimeter #}
{%- endfor %}
{% endif %}
!
{% if route_map is vyos_defined %}
ip protocol static route-map {{ route_map }}
!
{% endif %}
|