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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
|
{### MACRO definition for recurring peer patter, this can be either fed by a ###}
{### peer-group or an individual BGP neighbor ###}
{% macro bgp_neighbor(neighbor, config, peer_group=false) %}
{% if peer_group == true %}
neighbor {{ neighbor }} peer-group
{% elif config.peer_group is defined and config.peer_group is not none %}
neighbor {{ neighbor }} peer-group {{ config.peer_group }}
{% endif %}
{% if config.remote_as is defined and config.remote_as is not none %}
neighbor {{ neighbor }} remote-as {{ config.remote_as }}
{% endif %}
{% if config.advertisement_interval is defined and config.advertisement_interval is not none %}
neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }}
{% endif %}
{% if config.bfd is defined %}
neighbor {{ neighbor }} bfd
{% endif %}
{% if config.capability is defined and config.capability is not none %}
{% if config.capability.dynamic is defined %}
neighbor {{ neighbor }} capability dynamic
{% endif %}
{% if config.capability.extended_nexthop is defined %}
neighbor {{ neighbor }} capability extended-nexthop
{% endif %}
{% endif %}
{% if config.description is defined and config.description is not none %}
neighbor {{ neighbor }} description {{ config.description }}
{% endif %}
{% if config.disable_capability_negotiation is defined %}
neighbor {{ neighbor }} dont-capability-negotiate
{% endif %}
{% if config.ebgp_multihop is defined and config.ebgp_multihop is not none %}
neighbor {{ neighbor }} ebgp-multihop {{ config.ebgp_multihop }}
{% endif %}
{% if config.local_as is defined and config.local_as is not none %}
{% for local_asn in config.local_as %}
neighbor {{ neighbor }} local-as {{ local_asn }} {{ 'no-prepend' if config.local_as[local_asn].no_prepend is defined }}
{% endfor %}
{% endif %}
{% if config.override_capability is defined %}
neighbor {{ neighbor }} override-capability
{% endif %}
{% if config.passive is defined %}
neighbor {{ neighbor }} passive
{% endif %}
{% if config.password is defined and config.password is not none %}
neighbor {{ neighbor }} password {{ config.password }}
{% endif %}
{% if config.port is defined and config.port is not none %}
neighbor {{ neighbor }} port {{ config.port }}
{% endif %}
{% if config.shutdown is defined %}
neighbor {{ neighbor }} shutdown
{% endif %}
{% if config.strict_capability_match is defined %}
neighbor {{ neighbor }} strict-capability-match
{% endif %}
{% 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.update_source is defined and config.update_source is not none %}
neighbor {{ neighbor }} update-source {{ config.update_source }}
{% endif %}
{% if config.interface is defined and config.interface is not none %}
{% 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 }}
{% endif %}
{% if config.interface.v6only.remote_as is defined and config.interface.v6only.remote_as is not none %}
neighbor {{ neighbor }} interface v6only remote-as {{ config.interface.v6only.remote_as }}
{% endif %}
{% endif %}
{% endif %}
!
{% if config.address_family is defined and config.address_family is not none %}
{% for afi, afi_config in config.address_family.items() %}
{% if afi == 'ipv4_unicast' %}
address-family ipv4 unicast
{% elif afi == 'ipv6_unicast' %}
address-family ipv6 unicast
{% elif afi == 'l2vpn_evpn' %}
address-family l2vpn evpn
{% endif %}
{% if afi_config.addpath_tx_all is defined %}
neighbor {{ neighbor }} addpath-tx-all-paths
{% endif %}
{% if afi_config.addpath_tx_per_as is defined %}
neighbor {{ neighbor }} addpath-tx-bestpath-per-AS
{% endif %}
{% if afi_config.allowas_in is defined and afi_config.allowas_in is not none %}
neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is defined }}
{% endif %}
{% if afi_config.remove_private_as is defined %}
neighbor {{ neighbor }} remove-private-AS
{% endif %}
{% if afi_config.route_reflector_client is defined %}
neighbor {{ neighbor }} route-reflector-client
{% endif %}
{% if afi_config.weight is defined and afi_config.weight is not none %}
neighbor {{ neighbor }} weight {{ afi_config.weight }}
{% endif %}
{% 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.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 }}
{% endif %}
{% if afi_config.distribute_list is defined and afi_config.distribute_list is not none %}
{% if afi_config.distribute_list.export is defined and afi_config.distribute_list.export is not none %}
neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.export }} out
{% endif %}
{% if afi_config.distribute_list.import is defined and afi_config.distribute_list.import is not none %}
neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.import }} in
{% endif %}
{% endif %}
{% if afi_config.filter_list is defined and afi_config.filter_list is not none %}
{% if afi_config.filter_list.export is defined and afi_config.filter_list.export is not none %}
neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.export }} out
{% endif %}
{% if afi_config.filter_list.import is defined and afi_config.filter_list.import is not none %}
neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.import }} in
{% endif %}
{% endif %}
{% if afi_config.maximum_prefix is defined and afi_config.maximum_prefix is not none %}
neighbor {{ neighbor }} maximum-prefix {{ afi_config.maximum_prefix }}
{% endif %}
{% if afi_config.nexthop_self is defined %}
neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is defined }}
{% endif %}
{% if afi_config.route_server_client is defined %}
neighbor {{ neighbor }} route-server-client
{% endif %}
{% if afi_config.route_map is defined and afi_config.route_map is not none %}
{% if afi_config.route_map.export is defined and afi_config.route_map.export is not none %}
neighbor {{ neighbor }} route-map {{ afi_config.route_map.export }} out
{% endif %}
{% if afi_config.route_map.import is defined and afi_config.route_map.import is not none %}
neighbor {{ neighbor }} route-map {{ afi_config.route_map.import }} in
{% endif %}
{% endif %}
{% if afi_config.prefix_list is defined and afi_config.prefix_list is not none %}
{% if afi_config.prefix_list.export is defined and afi_config.prefix_list.export is not none %}
neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.export }} out
{% endif %}
{% if afi_config.prefix_list.import is defined and afi_config.prefix_list.import is not none %}
neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.import }} in
{% endif %}
{% endif %}
{% if afi_config.soft_reconfiguration is defined and afi_config.soft_reconfiguration.inbound is defined %}
neighbor {{ neighbor }} soft-reconfiguration inbound
{% endif %}
{% if afi_config.unsuppress_map is defined and afi_config.unsuppress_map is not none %}
neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }}
{% endif %}
{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.extended is defined %}
no neighbor {{ neighbor }} send-community extended
{% endif %}
{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.standard is defined %}
no neighbor {{ neighbor }} send-community standard
{% endif %}
neighbor {{ neighbor }} activate
exit-address-family
!
{% endfor %}
{% endif %}
{% endmacro %}
!
router bgp {{ asn }}
{# Disable eBGP policy by default until there is a CLI option #}
{# Workaround for T3183 until we have decided about a migration script #}
no bgp ebgp-requires-policy
{# 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() %}
!
{% if afi == 'ipv4_unicast' %}
address-family ipv4 unicast
{% elif afi == 'ipv6_unicast' %}
address-family ipv6 unicast
{% elif afi == 'l2vpn_evpn' %}
address-family l2vpn evpn
{% endif %}
{% if afi_config.aggregate_address is defined and afi_config.aggregate_address is not none %}
{% for ip in afi_config.aggregate_address %}
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.redistribute is defined and afi_config.redistribute is not none %}
{% for protocol in afi_config.redistribute %}
{% if protocol == 'table' %}
redistribute table {{ afi_config.redistribute[protocol].table }}
{% else %}
{% set redistribution_protocol = protocol %}
{% if protocol == 'ospfv3' %}
{% set redistribution_protocol = 'ospf6' %}
{% endif %}
redistribute {{ redistribution_protocol }}{% if afi_config.redistribute[protocol].metric is defined %} metric {{ afi_config.redistribute[protocol].metric }}{% endif %}{% if afi_config.redistribute[protocol].route_map is defined %} route-map {{ afi_config.redistribute[protocol].route_map }}{% endif %}
{####### we need this blank line!! #######}
{% endif %}
{% endfor %}
{% endif %}
{% if afi_config.network is defined and afi_config.network is not none %}
{% for network in afi_config.network %}
network {{ network }}{% if afi_config.network[network].route_map is defined %} route-map {{ afi_config.network[network].route_map }}{% endif %}{% if afi_config.network[network].backdoor is defined %} backdoor{% endif %}
{####### we need this blank line!! #######}
{% endfor %}
{% endif %}
{% if afi_config.advertise_all_vni is defined %}
advertise-all-vni
{% endif %}
{% if afi_config.advertise_default_gw is defined %}
advertise-default-gw
{% endif %}
{% if afi_config.advertise_pip is defined and afi_config.advertise_pip is not none %}
advertise-pip ip {{ afi_config.advertise_pip }}
{% endif %}
{% if afi_config.advertise_svi_ip is defined %}
advertise-svi-ip
{% endif %}
{% if afi_config.rt_auto_derive is defined %}
autort rfc8365-compatible
{% endif %}
{% if afi_config.flooding is defined and afi_config.flooding.disable is defined %}
flooding disable
{% endif %}
{% if afi_config.flooding is defined and afi_config.flooding.head_end_replication is defined %}
flooding head-end-replication
{% endif %}
{% if afi_config.rd is defined and afi_config.rd is not none %}
rd {{ afi_config.rd }}
{% endif %}
{% if afi_config.route_target is defined and afi_config.route_target is not none %}
{% if afi_config.route_target.both is defined and afi_config.route_target.both is not none %}
route-target both {{ afi_config.route_target.both }}
{% endif %}
{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %}
route-target export {{ afi_config.route_target.export }}
{% endif %}
{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %}
route-target import {{ afi_config.route_target.import }}
{% endif %}
{% endif %}
{% if afi_config.vni is defined and afi_config.vni is not none %}
{% for vni, vni_config in afi_config.vni.items() %}
vni {{ vni }}
{% if vni_config.advertise_default_gw is defined %}
advertise-default-gw
{% endif %}
{% if vni_config.advertise_svi_ip is defined %}
advertise-svi-ip
{% endif %}
exit-vni
{% endfor %}
{% endif %}
exit-address-family
{% 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) }}
{% endfor %}
{% endif %}
!
{% if neighbor is defined and neighbor is not none %}
{% for peer, config in neighbor.items() %}
{{ bgp_neighbor(peer, config) }}
{% endfor %}
{% endif %}
!
{% if listen is defined %}
{% if listen.limit is defined and listen.limit is not none %}
bgp listen limit {{ listen.limit }}
{% endif %}
{% for prefix, options in listen.range.items() %}
{% if options.peer_group is defined and options.peer_group is not none %}
bgp listen range {{ prefix }} peer-group {{ options.peer_group }}
{% endif %}
{% endfor %}
{% endif %}
{% if parameters is defined %}
{% if parameters.always_compare_med is defined %}
bgp always-compare-med
{% endif %}
{% if parameters.bestpath is defined and parameters.bestpath is not none %}
{% if parameters.bestpath.compare_routerid is defined %}
bgp bestpath compare-routerid
{% endif %}
{% if parameters.bestpath.as_path is defined and parameters.bestpath.as_path is not none %}
{% for option in parameters.bestpath.as_path %}
bgp bestpath as-path {{ option|replace('_', '-') }}
{% endfor %}
{% endif %}
{% if parameters.bestpath.med is defined and parameters.bestpath.med is not none %}
bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is defined }}
{% endif %}
{% endif %}
{% if parameters.cluster_id is defined and parameters.cluster_id is not none %}
bgp cluster-id {{ parameters.cluster_id }}
{% endif %}
{% if parameters.confederation is defined and parameters.confederation is not none %}
{% if parameters.confederation.identifier is defined and parameters.confederation.identifier is not none %}
bgp confederation identifier {{ parameters.confederation.identifier }}
{% endif %}
{% if parameters.confederation.peers is defined and parameters.confederation.peers is not none %}
bgp confederation peers {{ parameters.confederation.peers }}
{% endif %}
{% endif %}
{% if parameters.dampening is defined and parameters.dampening is defined and parameters.dampening.half_life is defined and parameters.dampening.half_life is not none %}
{# Doesn't work in current FRR configuration; vtysh (bgp dampening 16 751 2001 61) #}
bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is defined }}
{% endif %}
{% if parameters.default is defined and parameters.default is not none %}
{% if parameters.default.local_pref is defined and parameters.default.local_pref is not none %}
bgp default local-preference {{ parameters.default.local_pref }}
{% endif %}
{% if parameters.default.no_ipv4_unicast is defined %}
no bgp default ipv4-unicast
{% endif %}
{% endif %}
{% if parameters.deterministic_med is defined %}
bgp deterministic-med
{% endif %}
{% if parameters.distance is defined and parameters.distance is not none %}
!
address-family ipv4 unicast
{% if parameters.distance.global is defined and parameters.distance.global.external is defined and parameters.distance.global.internal is defined and parameters.distance.global.local is defined %}
distance bgp {{ parameters.distance.global.external }} {{ parameters.distance.global.internal }} {{ parameters.distance.global.local }}
{% endif %}
{% if parameters.distance.prefix is defined and parameters.distance.prefix is not none %}
{% for prefix in parameters.distance.prefix %}
distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }}
{% endfor %}
{% endif %}
exit-address-family
!
{% endif %}
{% if parameters.graceful_restart is defined %}
bgp graceful-restart {{ 'stalepath-time ' + parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is defined }}
{% endif %}
{% if parameters.graceful_shutdown is defined %}
bgp graceful-shutdown
{% endif %}
{% if parameters.log_neighbor_changes is defined %}
bgp log-neighbor-changes
{% endif %}
{% if parameters.network_import_check is defined %}
bgp network import-check
{% endif %}
{% if parameters.no_client_to_client_reflection is defined %}
no bgp client-to-client reflection
{% endif %}
{% if parameters.no_fast_external_failover is defined %}
no bgp fast-external-failover
{% endif %}
{% if parameters.router_id is defined and parameters.router_id is not none %}
bgp router-id {{ parameters.router_id }}
{% endif %}
{% endif %}
{% if timers is defined and timers.keepalive is defined and timers.holdtime is defined %}
timers bgp {{ timers.keepalive }} {{ timers.holdtime }}
{% endif %}
!
{% if route_map is defined and route_map is not none %}
ip protocol bgp route-map {{ route_map }}
{% endif %}
!
|