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:

  • actionpermit or deny

  • 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:

  • actionpermit or deny

  • 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