Generic Routing Tools Configuration Templates
This document describes the implementation details of the Generic Routing Configuration Module:
Still missing:
BGP AS-path filter data structure
BGP community filter data structure
Static routing data structure
Platform Capabilities
The routing policy/filtering capabilities of individual devices are specified in the device features.routing dictionary. That dictionary contains a key for every component supported by the routing module:
policy – routing policy capabilities
prefix – prefix filters (boolean)
aspath – AS path filters (boolean)
community – BGP community filter capabilities. expanded key indicates that the device can use regular expressions to match BGP communities.
The policy capability dictionary has two elements:
match – attributes the device can use in match conditions (prefix, nexthop, aspath, community)
set – attributes the device can use in set parameters (locpref, med, weight, prepend, community)
The match and set values could be a list of supported attributes or a dictionary of attributes in case you need to specify the capabilities of individual attributes.
When using the dictionary format, set the supported attribute values to true; the only set attribute that might need more details is the community attribute.
set.community can be a dictionary with the following values:
standard – device can change standard communities
large – device can change large communities
extended – device can change extended communities
append – device can append communities to a BGP route
For example, this is the capability definition for a device that can only set MED and local preference values:
features:
routing:
policy:
set: [ locpref, med ]
This is the FRRouting capability definition – it can do almost everything supported by the routing module:
routing:
policy:
set:
locpref: True
med: True
weight: True
prepend: True
community:
standard: True
large: True
extended: True
append: True
match: [ prefix, nexthop, aspath, community ]
prefix: True
aspath: True
community:
expanded: True
Prefix Filters Data Structure
The Prefix Filters (prefix-lists) are transformed into the routing.prefix dictionary:
The keys are the prefix filter names
The values are lists of prefix filter permit/deny conditions
Each entry in a prefix filter list contains these attributes:
action –
permit
ordeny
sequence – sequence number.
ipv4 (optional) – IPv4 prefix to match
ipv6 (optional) – IPv6 prefix to match
min (optional) – Minimum prefix length to match. A dictionary with optional ipv4 and ipv6 attributes
max (optional) – Maximum prefix length to match. A dictionary with optional ipv4 and ipv6 attributes
Tip
The prefix filter entries are sorted by their sequence numbers. If your platform does not require sequence numbers in prefix filters, you can ignore the sequence attribute.
For example, the following prefix filters (using named prefixes and pools)…
routing.prefix:
orig_1:
- prefix: b_orig_1
lb_only:
- pool: loopback
min:
ipv4: 32
ipv6: 64
max:
ipv4: 32
ipv6: 64
… are transformed into the following data structure:
routing.prefix:
lb_only:
- action: permit
ipv4: 10.0.0.0/24
ipv6: 2001:db8:1::/48
max:
ipv4: 32
ipv6: 64
min:
ipv4: 32
ipv6: 64
sequence: 10
orig_1:
- action: permit
ipv4: 172.42.42.0/24
sequence: 10
Many platforms cannot match IPv4 and IPv6 prefixes in the same prefix filter. netlab generates an additional routing._prefix dictionary for those platforms, extracting the IPv4 and IPv6 components of prefix filters into separate data structures. Here’s the routing._prefix data for the same example:
routing._prefix:
ipv4:
lb_only:
- action: permit
ipv4: 10.0.0.0/24
max: 32
min: 32
sequence: 10
orig_1:
- action: permit
ipv4: 172.42.42.0/24
sequence: 10
ipv6:
lb_only:
- action: permit
ipv6: 2001:db8:1::/48
max: 64
min: 64
sequence: 10
orig_1:
- action: deny
ipv6: ::/0
sequence: 10
It’s straightforward to use the routing._prefix data to generate IPv4 and IPv6 prefix lists:
Iterate over the address families. Use the node-level af attribute to iterate over address families used by a node.
Iterate over routing._prefix[afm] items
Create prefix-list entries.
Here’s the template used to generate prefix lists for platforms using industry-standard[1] prefix lists:
{%- macro min_max(p_entry) -%}
{%- if 'min' in p_entry %} ge {{ p_entry.min }}{% endif -%}
{%- if 'max' in p_entry %} le {{ p_entry.max }}{% endif -%}
{%- endmacro -%}
!
{% for pf_af in af if pf_af in routing._prefix|default({}) %}
{% for p_name,p_value in routing._prefix[pf_af].items() %}
!
{% for p_entry in p_value %}
{%. af_kw = 'ip' if pf_af == 'ipv4' else pf_af %}
{{ af_kw }} prefix-list {{ p_name
}}-{{ pf_af }} seq {{ p_entry.sequence }} {{ p_entry.action
}} {{ p_entry[pf_af] }}{{ min_max(p_entry) }}
{% endfor %}
{% endfor %}
{% endfor %}
Notes:
The template generates two prefix lists: name-ipv4 and name-ipv6. We have to use distinct names because some platforms don’t like having IPv4 and IPv6 prefix lists with the same name.
We need the af_kw variable because Cisco IOS CLI uses ip prefix-list and ipv6 prefix-list
The min_max macro is used to make the generation of ge/le keywords a bit more readable.
The address family complexity can be avoided on platforms that can match IPv4 and IPv6 prefixes in the same prefix filter. Here’s the SR Linux template:
{% for pf_name,pf_list in routing.prefix|default({})|items %}
- path: /routing-policy/prefix-set[name={{ pf_name }}]
value:
prefix:
{% for p_entry in pf_list %}{# Iterate over prefix list entries #}
{% for p_af in af if p_af in p_entry %}{# Iterate over address families in the prefix list entry #}
- ip-prefix: {{ p_entry[p_af] }}
{% if p_entry.min[p_af] is defined or p_entry.max[p_af] is defined %}
mask-length-range: {{
p_entry.min[p_af]|default(p_entry[p_af]|ipaddr('prefix')) }}..{{
p_entry.max[p_af]|default(32 if p_af == 'ipv4' else 128) }}
{% else %}
mask-length-range: exact
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
Notes:
The SR Linux prefix sets don’t have sequence or deny options (the lack of deny action is handled as a device quirk)
SR Linux uses ip-prefix attribute to specify both IPv4 and IPv6 prefixes, so we have to iterate over address families to generate two list entries when a single prefix list item contains ipv4 and ipv6 values.
The mask-length-range parameter must be in the a…b format, so we have to specify the default minimum and maximum lengths when they’re missing.
Routing Policy Data Structure
The Routing Policies are transformed into the routing.policy dictionary:
The keys are the routing policy (route map) names
The values are lists of routing policy (route map) statements (match/set values)
Each entry in a routing policy list contains these attributes:
action –
permit
ordeny
sequence – sequence number.
set – a dictionary of set actions
match – a dictionary of match conditions
Tip
The routing policy entries are sorted by their sequence numbers. If your platform does not require sequence numbers in route maps, you can ignore the sequence attribute.
The match conditions in a routing policy entry include:
prefix – match the route with an IPv4 or IPv6 prefix filter
aspath – match a BGP AS-path with an AS-path filter
nexthop – match the route next hop with an IPv4 or IPv6 prefix filter
community – match BGP communities with a BGP community filter
The set actions include:
locpref – set local preference
med – set route metric (usually used to set BGP MED attribute)
weight – set BGP weight
prepend – do BGP AS-path prepending
community – change BGP communities attached to a route