Routing Configuration
Configure the control plane: the IGP (IS-IS) that carries router loopback reachability, and BGP that announces subscribers and peers with upstream.
Overview
AthenaBNG uses a two-plane routing design:
- IS-IS is the IGP. Its only job is to carry the router loopback
reachability (IPv4
/32and, dual-stack, IPv6/128) across the core so that iBGP can peer loopback-to-loopback. Subscribers are not in the IGP. - BGP carries subscribers and upstream peering. Subscriber reachability is
announced as a route policy over BGP — per-
/32host routes for IPv4, and a single summary aggregate for IPv6. - OSPF is still supported (
routing.ospf) but IS-IS is the recommended and current IGP. See BGP/OSPF Integration for the OSPF-to-IS-IS migration story. - Static routes (
routing.static_routes) can be added for anything the dynamic protocols don't cover.
The routing section has four sub-sections: bgp, isis, ospf, and
static_routes. The router identities it depends on live under system.
Router identity (system)
Routing keys off two system-level fields:
system:
router_id: "10.255.0.4" # IPv4 loopback — BGP router-id + IS-IS export
router_id_v6: "2001:df4:2040::4" # optional IPv6 loopback for the dual-stack plane
router_id
The IPv4 loopback. Placed on lo as a /32, used as the BGP router-id, the
IS-IS export target, and (by default) the RADIUS NAS-IP. It is always excluded
from subscriber prefixes so it is only ever reachable via the IGP.
Type: IPv4 address Required: Yes
router_id_v6
Optional IPv6 loopback for the dual-stack control plane. When set it is placed on
lo as a /128 and announced into IS-IS, giving v6 next-hops (and v6 iBGP peers)
reachability. Leave unset for IPv4-only deployments — all v6 rendering is gated off.
Type: IPv6 address Required: No Default: unset
isis
IS-IS is a single, dual-stack (IPv4 + IPv6) protocol instance, single-topology,
metric-style wide. It advertises only the loopback(s).
routing:
isis:
enabled: true
net: "49.0001.0000.0000.0004.00"
level: level-2
ipv6: true
announce_loopback: true
redistribute_subscriber_routes: false
interfaces:
- name: upstream0
circuit_type: level-2
network_type: point-to-point
metric: 10
enabled
Enable IS-IS.
Type: Boolean Default: false
net
Network Entity Title (NET) — the IS-IS system identity. Format
AA.NNNN.SSSS.SSSS.SSSS.00 (area, 6-byte system-id, NSEL 00). Each router needs
a unique system-id.
Type: String Required: Yes (if IS-IS enabled) Example: 49.0001.0000.0000.0004.00
level
IS type / level for the instance.
Type: String Default: level-2 Valid values: level-1, level-2, level-1-2
ipv6
Advertise the IPv6 address-family in addition to IPv4 (single dual-stack instance).
Type: Boolean Default: true
announce_loopback
Announce the router loopback into IS-IS — this is the IGP's whole purpose in this
design. The IPv4 /32 is exported with redistribute ipv4 connected … route-map ISIS-EXPORT (matched to router_id/32 only). The IPv6 /128, when
system.router_id_v6 is set, is advertised via a passive interface lo
stanza (ipv6 router isis + isis passive) rather than redistribute ipv6 connected — FRR isisd does not emit loopback /128s through redistribute the way
it does for IPv4, so the loopback is activated passively (no hellos, just its
address).
Type: Boolean Default: true
redistribute_subscriber_routes
Redistribute connected/static/kernel (subscriber) routes into IS-IS. Off by default — subscribers go over BGP, not the IGP. Enable only if you deliberately want subscriber host routes in IS-IS too.
Type: Boolean Default: false
interfaces
Per-interface IS-IS activation. Each entry activates ip router isis (and ipv6 router isis when ipv6: true) on the named interface.
interfaces:
- name: upstream0
circuit_type: level-2 # level-1 | level-2 | level-1-2 (optional)
network_type: point-to-point # point-to-point | broadcast (optional)
metric: 10 # optional
passive: false # advertise subnet, send no hellos (optional)
- name — interface name (required).
- circuit_type — per-interface level (optional).
- network_type —
point-to-pointavoids DIS election on P2P core links (optional). - metric — IS-IS metric (optional).
- passive — advertise the interface subnet but send no hellos (optional).
bgp
BGP announces subscribers and peers upstream. Neighbours may be IPv4 or IPv6
addresses; iBGP peers loopback-to-loopback with update-source lo.
routing:
bgp:
enabled: true
asn: 64512
neighbors:
- address: "10.255.0.1" # IPv4 loopback of the peer
remote_as: 64512
description: "BDR1 (iBGP)"
update_source: "lo"
- address: "2001:df4:2040::1" # IPv6 loopback of the peer
remote_as: 64512
description: "BDR1 (iBGP v6)"
update_source: "lo"
announce_subscriber_routes: true
subscriber_networks:
- "100.64.0.0/10"
host_routes_only: true
community: "64512:100"
announce_subscriber_routes_v6: true
subscriber_networks_v6:
- "2001:df4:2040:1000::/52"
enabled
Enable BGP.
Type: Boolean Default: false
asn
Local Autonomous System Number.
Type: Integer (1–4294967295) Required: Yes (if BGP enabled)
Private ranges: 64512–65534 (16-bit), 4200000000–4294967294 (32-bit).
neighbors
BGP neighbour list. Each neighbour:
- address — neighbour IP, IPv4 or IPv6 (required). IPv6 addresses are placed in a separate v6 peer-group automatically.
- remote_as — neighbour ASN (required). Equal to
asnfor iBGP. - description — free-text label (optional).
- update_source — source interface/address for the session (optional). For
loopback-to-loopback iBGP set this to
lo.
announce_subscriber_routes
Announce IPv4 subscriber routes over BGP.
Type: Boolean Default: true
When on, subscriber host routes are redistributed (connected/static/kernel) into
the IPv4 unicast AF through the SUB-ROUTES-TO-BGP route-map.
subscriber_networks
Supernets subscriber IPv4 addresses are drawn from. BGP only announces host routes
that fall within these. Empty (default) = any prefix, subject to
host_routes_only. The router loopback is always excluded.
Type: List of CIDR Default: [] (any)
host_routes_only
Only announce /32 host routes. Set false to announce the configured
subscriber_networks at their natural prefix length instead (a summarised
announcement).
Type: Boolean Default: true
community
BGP community string to tag announced subscriber routes with (applied in both the
v4 and v6 route-maps). send-community behaviour follows FRR defaults.
Type: String Default: unset Example: "64512:100"
announce_subscriber_routes_v6
Announce subscriber IPv6 (delegated prefixes) over BGP's IPv6 unicast AF.
Off by default. When on, the template adds the v6 address-family, a separate
UPSTREAM6 peer-group for IPv6 neighbours, no bgp default ipv4-unicast (so a v6
peer is not auto-activated for v4), and the aggregate-only announcement described
below.
Type: Boolean Default: false
subscriber_networks_v6
IPv6 supernets subscriber delegated prefixes are drawn from. Unlike IPv4, only
the aggregate is announced — each entry renders aggregate-address <net> summary-only, and a matching ipv6 route <net> blackhole gives the aggregate a
contributing route so it originates even with zero active subscribers (and
discards traffic to unallocated space). Per-customer /56//60 more-specifics
forward locally but are suppressed from BGP. The v6 loopback is always excluded.
Type: List of CIDR Default: []
ospf
Legacy IGP option. Prefer IS-IS. When enabled it redistributes the loopback
(via CONNECTED-TO-OSPF, matched to interface lo) and static routes.
routing:
ospf:
enabled: false
area: "0.0.0.0"
networks:
- "10.255.0.0/24"
passive_interfaces:
- "upstream0"
- enabled — Boolean, default false.
- area — OSPF area for the
networkstatements. Default0.0.0.0. - networks — list of networks to run OSPF on (each added as
network <net> area <area>). - passive_interfaces — interfaces to advertise but send no hellos on.
static_routes
Static routes redistributed into the IGP and BGP where policy allows.
routing:
static_routes:
- prefix: "192.0.2.0/24"
next_hop: "10.255.0.1"
- prefix: "198.51.100.0/24"
interface: "upstream0"
- prefix — destination CIDR (required).
- next_hop — gateway IP (optional).
- interface — egress interface (optional).
Example configurations
Dual-stack core (IS-IS + iBGP)
system:
router_id: "10.255.0.4"
router_id_v6: "2001:df4:2040::4"
routing:
isis:
enabled: true
net: "49.0001.0000.0000.0004.00"
level: level-2
ipv6: true
interfaces:
- name: upstream0
network_type: point-to-point
metric: 10
bgp:
enabled: true
asn: 64512
neighbors:
- address: "10.255.0.1"
remote_as: 64512
update_source: "lo"
- address: "2001:df4:2040::1"
remote_as: 64512
update_source: "lo"
announce_subscriber_routes: true
subscriber_networks: ["100.64.0.0/10"]
announce_subscriber_routes_v6: true
subscriber_networks_v6: ["2001:df4:2040:1000::/52"]
IPv4-only
system:
router_id: "10.255.0.4"
routing:
isis:
enabled: true
net: "49.0001.0000.0000.0004.00"
interfaces:
- name: upstream0
network_type: point-to-point
bgp:
enabled: true
asn: 64512
neighbors:
- address: "10.255.0.1"
remote_as: 64512
update_source: "lo"
announce_subscriber_routes: true
subscriber_networks: ["203.0.113.0/24"]
With router_id_v6 unset and announce_subscriber_routes_v6 off, the rendered
FRR is byte-identical to a pre-IPv6 build.
Configuration via CLI
abng> configure
abng# set system router_id 10.255.0.4
abng# set system router_id_v6 2001:df4:2040::4
abng# set routing isis enabled true
abng# set routing isis net 49.0001.0000.0000.0004.00
abng# set routing bgp enabled true
abng# set routing bgp asn 64512
abng# set routing bgp neighbors[0] address 10.255.0.1
abng# set routing bgp neighbors[0] remote_as 64512
abng# set routing bgp neighbors[0] update_source lo
abng# set routing bgp announce_subscriber_routes_v6 true
abng# commit
Rendered FRR (concepts)
The commit pipeline renders frr.conf from the config above. The key pieces:
! Loopback carries both identities; the v6 /128 is announced into IS-IS passively
interface lo
ip address 10.255.0.4/32
ipv6 address 2001:df4:2040::4/128
! IGP: loopback-only export
ip prefix-list ISIS-LOOPBACK seq 5 permit 10.255.0.4/32
router isis AthenaBNG
net 49.0001.0000.0000.0004.00
is-type level-2
metric-style wide
redistribute ipv4 connected level-2 route-map ISIS-EXPORT
interface lo
ipv6 router isis AthenaBNG
isis passive
! IPv4 subscribers: per-/32 host routes, loopback excluded
ip prefix-list SUBSCRIBER-PREFIXES seq 5 deny 10.255.0.4/32
ip prefix-list SUBSCRIBER-PREFIXES seq 10 permit 100.64.0.0/10 ge 32 le 32
! IPv6 subscribers: aggregate only, with a blackhole contributor
ipv6 route 2001:df4:2040:1000::/52 blackhole
router bgp 64512
bgp router-id 10.255.0.4
no bgp default ipv4-unicast
neighbor UPSTREAM peer-group
neighbor UPSTREAM6 peer-group
neighbor 10.255.0.1 peer-group UPSTREAM
neighbor 10.255.0.1 remote-as 64512
neighbor 10.255.0.1 update-source lo
neighbor 2001:df4:2040::1 peer-group UPSTREAM6
neighbor 2001:df4:2040::1 remote-as 64512
neighbor 2001:df4:2040::1 update-source lo
address-family ipv4 unicast
redistribute connected route-map SUB-ROUTES-TO-BGP
neighbor UPSTREAM activate
exit-address-family
address-family ipv6 unicast
aggregate-address 2001:df4:2040:1000::/52 summary-only
neighbor UPSTREAM6 activate
neighbor UPSTREAM6 next-hop-self
exit-address-family
Verification
abng> show bgp summary
abng> show routes
sudo vtysh -c "show isis neighbor"
sudo vtysh -c "show isis database"
sudo vtysh -c "show bgp ipv4 unicast"
sudo vtysh -c "show bgp ipv6 unicast"
Validation rules
| Field | Validation |
|---|---|
system.router_id | Valid IPv4 address |
system.router_id_v6 | Valid IPv6 address (optional) |
isis.enabled | Boolean |
isis.net | Valid NET (required if IS-IS enabled) |
isis.level | level-1 | level-2 | level-1-2 |
isis.interfaces[].network_type | point-to-point | broadcast |
bgp.asn | Integer 1–4294967295 |
bgp.neighbors[].address | Valid IPv4 or IPv6 address |
bgp.neighbors[].remote_as | Integer 1–4294967295 |
bgp.subscriber_networks[] | Valid IPv4 CIDR |
bgp.subscriber_networks_v6[] | Valid IPv6 CIDR |
ospf.area | Valid area id |
Best practices
- IGP scope — keep IS-IS loopback-only (
redistribute_subscriber_routes: false); let BGP carry subscribers. - Loopback identities — set both
router_idandrouter_id_v6for dual-stack; peer iBGP loopback-to-loopback withupdate_source: lo. - P2P core links — use
network_type: point-to-pointon IS-IS core interfaces to skip DIS election. - IPv6 announcement — announce the aggregate (
subscriber_networks_v6), never the per-customer more-specifics. - ASN — private ranges (64512–65534 or 4200000000+) unless you hold a public ASN.
- Monitoring — watch BGP session state, IS-IS adjacencies, and route counts.
Troubleshooting
iBGP session not establishing
- Confirm the peer loopback is reachable via IS-IS:
sudo vtysh -c "show isis database", thenping <peer-loopback>. - Confirm
update_source: loon both ends. - For a v6 peer, confirm
router_id_v6is set and the v6 loopback is in IS-IS.
Subscriber routes not advertised
- IPv4: check
announce_subscriber_routesand that the subscriber IP falls withinsubscriber_networks;sudo vtysh -c "show bgp ipv4 unicast". - IPv6: the per-customer prefixes are intentionally suppressed — verify the
aggregate instead:
sudo vtysh -c "show bgp ipv6 unicast 2001:df4:2040:1000::/52".
IS-IS adjacency down
sudo vtysh -c "show isis neighbor".- Confirm the interface is listed under
isis.interfacesand both ends agree onnetwork_typeand level.
Next steps
- BGP/OSPF Integration — upstream interop and topology
- Routing feature overview — how the routing plane works
- Configuration Overview — all configuration sections