Prefix Sets: Simplifying netlab ACLs and Prefix Filters
When I implemented prefix filters in netlab (release 1.9.0), I wanted them to match the final device configurations as closely as possible, including the one prefix per entry rule to match the device configuration sequence numbers. That worked well, but resulted in YAML bloat, since each matching prefix requires several lines of YAML.
We tried to use the same approach with ACLs but quickly gave up when we realized the port not in range operation requires multiple ACL entries on most platforms. With the matching sequence numbers paradigm gone with the wind, it made no sense to limit ourselves to one prefix per ACL entry – the initial ACL entry implementation already accepted lists of prefixes and expanded them into ACL entries.
Mistakenly1, we also copied the prefix-specification mechanism from prefix filters into ACLs: each entry accepted a number of parameters (prefix, pool, ipv4, ipv6, node…) that resulted in IP prefix(es) from different netlab objects. However, once we started rolling, the ideas didn’t stop there. It would be nice to match on VLAN prefixes and link prefixes based on a link ID or role. It was time for a redesign, resulting in generic prefix sets introduced in release 25.09:
- A prefix set is a list of prefixes
- Every prefix is either an IPv4/IPv6 address, an IPv4/IPv6 prefix, or an object descriptor
- An object descriptor has a namespace (pool, vlan…) and an object ID, separated by a dot (for example,
vlan.red). You can find the complete list of object namespaces in the netlab documentation.
For example, you can use this simple definition to allow all traffic from LAN subnets and loopbacks (assuming you use automatic address assignments):
routing.acl:
endpoints:
- protocol: ip
src.prefix: [ pool.lan, pool.loopback ]
It generates this ACL on Arista EOS:
ip access-list endpoints_ipv4
100 permit ip 172.16.0.0/16 any
110 permit ip 10.0.0.0/24 any
After cleaning up the ACL implementation, it was time to implement the same mechanism for prefix filters:
- Each prefix-specifying argument can be a list (previously, they only accepted a single value)
- You can use the prefix argument to specify a prefix set.
For example, the following topology using dual-stack loopbacks and a named prefix specifies a prefix filter containing a pool definition, a named prefix, and a literal IPv6 prefix:
module: [ routing ]
addressing.loopback.ipv6: 2001:db8::/48
prefix.alpha.ipv4: 192.168.42.0/24
nodes:
rtr:
routing.prefix:
example:
- prefix: [ pool.loopback, prefix.alpha, 2001:db8:cafe:2::/64 ]
Based on the example prefix filter definition, netlab generates two prefix lists on Arista EOS:
ip prefix-list example-ipv4 seq 100 permit 10.0.0.0/24ip prefix-list example-ipv4 seq 110 permit 192.168.42.0/24!ipv6 prefix-list example-ipv6seq 100 permit 2001:db8::/48seq 110 permit 2001:db8:cafe:2::/64
Cisco IOS XR can accept IPv4 and IPv6 prefixes in the same prefix set. netlab thus generates the following prefix set based on the above lab topology:
prefix-set example10.0.0.0/24,192.168.42.0/24,2001:db8::/48,2001:db8:cafe:2::/64end-set
-
Following the do more with less mantra popularized by the techbros. ↩︎