Routing¶
Routing is where you write down how a device or a virtual machine forwards - the static routes it carries, and the policy objects every routing protocol shares: prefix lists, communities, community lists, AS-path lists, routing policies (route maps) and the keychains sessions authenticate with. BGP, OSPF, IS-IS, EIGRP and the EVPN/VXLAN overlay build on these; two complete templates, NX-OS style and FRR, rendered from an opt-in demo fabric, are on Routing templates.
Two ideas run through the whole module:
- Catalogs are tenant-wide, instances are per box. A prefix list or a policy is named once and used on every router; a static route, a BGP session or an OSPF interface belongs to one device or one virtual machine and is scoped to its site like that box is. See Routing on virtual machines.
- Danbyte renders what is modelled; the template is yours. Everything
here reaches a device's config template
as a
routingblock, so one template renders the whole box - in whatever vendor's syntax you write it in.make seed-fabricgives you a leaf/spine fabric to render against.
Prefix lists¶
Routing → Prefix lists → Add prefix list. A prefix list has a name, a family (IPv4 or IPv6) and its rules, edited together on one page:
| Column | What it records |
|---|---|
| Seq | The sequence number - rules are evaluated in order. "Add rule" takes the last one plus ten. |
| Action | permit or deny. |
| Prefix | The network, in CIDR. Host bits set is an error - 10.0.0.1/8 means you meant 10.0.0.0/8. |
| ge / le | The length range this line matches, as on the box (10.0.0.0/8 ge 24 le 32). Both must sit between the prefix's own length and 32 (128 for IPv6). |
| Description | Optional. |
Saving writes the rule set as a whole: a rule is matched by sequence and rewritten, sequences you removed are deleted. The list page shows the rule count; the list's own page shows the rules.
Communities and community lists¶
A community is a BGP community value with a name, so 65000:100 reads
as CUSTOMER-ROUTES wherever it is set or matched. Standard, large and
extended communities are told apart by their kind; the value is unique per
tenant.
A community list matches communities. A standard, large or
extended list names the communities each rule matches; an expanded list
matches a pattern instead (^65000:1..$).
AS-path lists¶
Patterns over the AS path a policy matches on - ^65010_ for "learned
from 65010", _65020$ for "originated by 65020". One pattern per rule.
Routing policies¶
A routing policy is a route map: ordered rules, each of which matches and sets.
| Match | What it tests |
|---|---|
| Prefix lists | The route's prefix is permitted by any of them. |
| Community lists | The route carries a community any of them permits. |
| AS-path lists | The route's AS path matches any of them. |
| Next hop in | The next hop is in the named prefix list. |
| Set | What it changes |
|---|---|
| Local pref, MED, weight | The BGP attributes. |
| Origin | igp, egp or incomplete. |
| Next hop | Rewrite the next hop. |
| AS-path prepend | 65001 65001 - as many as you type. |
| Communities (+ additive) | Set, or add to, the route's communities. |
| Metric type | Type 1 or 2 for OSPF redistribution. |
| Continue | Jump to another sequence after this one matches. |
A vendor knob Danbyte does not model goes in the rule's match_extra /
set_extra JSON through the API; a template reads it as rule.match.foo.
Keychains¶
Routing → Keychains. The one secret-bearing routing object: BGP sessions
and OSPF / IS-IS interfaces reference a keychain, and the key itself lives in
the deployment's secret store, never in the row -
the same arrangement an SSID's or an IPsec profile's pre-shared key uses.
Without a store the key is refused rather than stored in the clear. A
keychain's page shows Stored with a reveal button (an audited action
behind the reveal grant on keychains) or Not set; the rendered config
never carries the key. Where a template needs one it prints the
placeholder <keychain:NAME> (routing.keychain_by_name[NAME].placeholder
carries it ready-made); that shape is a promise, and a push tool replaces
every match with the key from POST /api/routing/keychains/<id>/reveal-psk/
or its own store - see secrets in a
render.
BFD¶
BFD is switched on where it applies - an instance (every neighbour or
interface of the process), one enrolled interface, a peer group or one
session - and every one of those places can name a BFD profile: the
timers BFD runs with, named once under Routing → BFD profiles (min TX,
min RX in milliseconds, the detect multiplier, echo mode), the shape FRR's
bfd profile and NX-OS's bfd-template have. A profile is optional; none
means the platform's default timers. Resolution runs down the chain the
way the other settings do: an interface row's profile, else its
instance's; a session's, else its peer group's, else its instance's.
Deleting a profile leaves BFD on and the timers at the default.
Static routes¶
Routing → Static routes, or a device's or VM's Routing tab. One row is one path on one box:
| Field | What it records |
|---|---|
| Runs on | The router: a device or a virtual machine. |
| VRF | The table the route sits in; blank is the global table. |
| Prefix | The destination, in CIDR, normalised the way the box prints it. |
| IPAM prefix | Optionally, the prefix object this route names, so the prefix's page can show who routes it. |
| Kind | Next hop, interface, blackhole or reject. |
| Next hop / Interface | For a next-hop route: an address, an interface on the same device, or both (ip route 0.0.0.0/0 10.1.1.1 eth0). An interface route points out of a port with no address - the point-to-point shape some platforms write (ip route 10.30.0.0/16 Serial0/0). |
| Next hop VRF | Route leaking - the table the next hop is looked up in. |
| Distance, Metric, Tag, BFD | As on the box; blank means the platform default. |
| Status | Your own status catalog; the built-ins are active, planned and disabled. |
The same prefix through two next hops is two rows (ECMP); the same path twice is refused. A next-hop interface on another box is refused too.
BGP¶
BGP is three objects: the instance (router bgp on a device, one per
table), its address families, and the sessions (neighbours), with
peer groups as the tenant-wide catalog a session inherits from.
Instances and address families¶
A device's Routing tab → Add instance: the AS (from ASNs),
the VRF (blank = the global table), router ID, cluster ID, graceful
restart, and BFD as the default for its neighbours. Each instance carries
its address families - ipv4-unicast, ipv6-unicast, vpnv4-unicast,
vpnv6-unicast, l2vpn-evpn, ipv4-labeled-unicast - each with the
networks it originates, maximum paths, an import and export policy, and
what it redistributes (connected, static, OSPF, …, each through a
policy).
Peer groups¶
Routing → BGP peer groups. The neighbour settings named once - remote AS
(a number, or external / internal for unnumbered fabrics), a local AS
override, an update source hint, address families, policies, BFD, eBGP
multihop TTL, next-hop self, route-reflector client, send-community,
timers, and the keychain. A group is not bound to a device: the same
SPINES group applies on every leaf.
Sessions¶
Routing → BGP sessions, or the instance's Add session. A session
names its far end as an address or as an interface (unnumbered
peering - neighbor swp1 interface remote-as external), its local address
(whose interface is the update source), and optionally the peer device.
When the far address is in IPAM, the row is linked and the peer device is
filled in.
Whether a session is iBGP or eBGP is never typed in: the same AS on both
ends is internal, anything else external (an unnumbered internal /
external remote AS says so directly). It shows as a badge on the session,
filters the sessions list, and reaches a template as session.kind.
Every neighbour setting a session leaves on Inherit comes from its peer
group; what neither sets falls to the instance (BFD, the BFD profile) or
the platform default. The settings are the address families, import and
export policy, BFD and its profile, eBGP multihop, next-hop self, route
reflector client, send community, keepalive and hold time, the keychain,
and the day-one neighbour knobs: default originate, maximum
prefix, allowas-in, AS override, remove private AS and
soft reconfiguration. The session's page shows both: Effective settings - what the
box ends up with - and Own values. The API returns the same as
effective, and the render context carries only effective values, so a
template never repeats the resolution.
Sessions whose far end is a device Danbyte knows draw on the topology map as their own link family - a dotted line per device pair and table, hidden with the eyes like any other family, with the session a click away.
Create the far end on a session's page writes the mirror session on the peer device - its instance in the same table, addresses swapped, the effective settings copied - and links the two, so an iBGP pair is two clicks. It needs the peer device, this side's local address and a far address IPAM has on that device.
OSPF¶
OSPF areas (Routing → OSPF areas) are a tenant catalog: the backbone and
the areas behind it, each with an ID (0 or 0.0.0.0 - a plain number
stays a number, a dotted quad is normalised) and a kind (normal, stub,
totally stubby, NSSA, totally NSSA).
An OSPF instance lives on a device's Routing tab: the process (a number on IOS, a name on NX-OS and FRR), the version (v2/v3), the VRF, router ID, reference bandwidth, passive by default, default-originate, BFD, and what it redistributes. One instance per device, table, version and process.
Interfaces enrol in an instance from its card - one row per port, with the area, cost, network type, passive (blank = the instance's default), priority, hello/dead timers, BFD, MTU-ignore, and authentication with a keychain. A port enrols in an instance once; a port on another device is refused.
IS-IS¶
An IS-IS instance has a process name, the NET (checked to read like
one - 49.0001.0000.0000.0011.00), an optional router ID, the level (1, 2,
1-2), metric style, BFD, area authentication with a keychain, and
redistribution. One per device and process. All of it sits on the
instance card of the device's Routing tab (net …, router-id …, level
…) and in its edit dialog.
Timers & LSP on the same dialog: lsp-gen-interval, spf-interval,
lsp-mtu, the five spf-delay-ietf values (all or none), log adjacency
changes, and default-information originate per family (off, when a
default exists, always). Redistribution rows on IS-IS carry a family
and a level; a blank level means the instance's own. Knobs Danbyte
still does not name - overload bit, multi-topology - go in the instance's
extra and reach the template as inst.extra.<key>. The template gets the
level as FRR spells it (inst.level_frr is level-2-only), so it keeps no
mapping of its own.
Interfaces enrol with their families (ipv4, ipv6 - FRR needs ip
router isis per family), a level override, metric (and an L2 metric when
the levels differ), network type, passive, hello interval and multiplier,
BFD, and hello authentication.
An interface's own page shows the OSPF and IS-IS rows it sits in, and any unnumbered BGP session on it, under Routing.
EIGRP¶
An EIGRP instance is router eigrp <AS> on a device, in one table: the
AS number (1-65535), an optional name for named mode (router eigrp
NAME with the AS under its address family), router ID, K values (1 0
1 0 0; blank is the platform default), variance, maximum paths, passive by
default, stub, BFD, and redistribution. One per device, VRF and AS.
Interfaces enrol with passive (null = the instance default), split horizon
(null = the platform default), hello and hold timers, bandwidth percent,
summary addresses (ip summary-address eigrp, checked as networks),
BFD, and MD5 or HMAC-SHA-256 authentication with a keychain.
An IOS fragment:
{% for inst in routing.eigrp %}
router eigrp {{ inst.name or inst.asn }}
{% if inst.name %}
address-family ipv4 unicast autonomous-system {{ inst.asn }}
{% endif %}
{% if inst.router_id %}
eigrp router-id {{ inst.router_id }}
{% endif %}
{% if inst.k_values %}
metric weights 0 {{ inst.k_values }}
{% endif %}
{% if inst.stub %}
eigrp stub connected summary
{% endif %}
{% for r in inst.redistribute %}
redistribute {{ r.source }}{% if r.policy %} route-map {{ r.policy }}{% endif %}
{% endfor %}
{% for i in inst.interfaces if i.passive %}
passive-interface {{ i.interface }}
{% endfor %}
{% endfor %}
Overlay: EVPN and VXLAN¶
The overlay builds on the L2VPN you already have: an L2VPN of a VXLAN type is the VNI, its terminations say which VLAN carries it at each site, its route targets are the EVPN import/export targets. Two things are added for it:
- An EVPN L2VPN (
vxlan-evpn,mpls-evpn) can name a VRF. That makes it the VRF's L3VNI - the symmetric-IRB VNI that routes between the VRF's subnets on every leaf. Other types refuse a VRF; a VNI is unique per tenant across the VXLAN types, so two overlays cannot claim 10100. - A device gets a VTEP - one per device, on the Routing tab - with its source interface (the loopback tunnels come from), source IP, an optional anycast IP for an MLAG pair, the anycast gateway MAC and ARP suppression. The VNIs the leaf carries are rows on the VTEP: pick the L2VPN, and optionally a device-local VLAN, a per-leaf RD, ingress replication or a multicast group.
A VNI's VLAN on a given leaf resolves in this order: the membership's own VLAN → the L2VPN's termination on a VLAN at the device's site → the L2VPN's sole VLAN termination → none. A VNI stretched across sites therefore needs one termination per site and nothing on the leaves; an L3VNI, which no termination names, gets its VLAN on the membership when the platform wants one (NX-OS does, FRR does not).
The anycast gateway itself is an ordinary SVI: a virtual interface in the VRF, with the shared address assigned through an FHRP group of protocol EVPN anycast gateway. That is the whole trick for "the same address on every leaf": the address exists once, as the group's virtual IP, and the group is assigned to each leaf's SVI - do not create the address per leaf, which the uniqueness rule refuses. An anycast group also carries the SVI's IPv6 neighbour discovery: whether it sends router advertisements and at what interval; the subnet it announces is the gateway's own prefix. The render hands all of it to the SVI loop (see templates).
An L2VPN's page lists the VTEPs carrying it; a VLAN's page lists the
L2VPNs terminating on it. The l2vpn-evpn address family on the BGP
instance and its sessions is what carries the overlay's routes - nothing
else is needed on the BGP side. A fabric session usually also turns on
extended next-hop (RFC 5549, IPv4 over an IPv6 next hop) and TTL
security (GTSM); both are knobs on a session or its peer group.
Multihoming: Ethernet segments¶
A server plugged into two leaves is one Ethernet segment: the LAG on
each leaf, sharing one identity. Routing → Ethernet segments is that
catalog. A segment is named either by a full ten-octet ESI (type 0) or
by an es-id and a system MAC (type 3, which is what FRR's evpn mh
es-id / es-sys-mac take), carries the DF preference that decides who
forwards BUM traffic, and lists its member interfaces - on different
devices, which is the point: the segment page is where a reviewer sees that
leaf1 bond1 and leaf2 bond1 are the same server. An interface's page
shows the segment it is in.
Each fabric-facing port on a multihomed leaf is marked EVPN MH uplink
on the interface form (evpn mh uplink): FRR watches those to decide
whether the leaf has lost the fabric and should stop forwarding for its
segments. The render hands a template by_interface[port].es,
by_interface[port].evpn_mh_uplink, the device's ethernet_segments and
es_count - a device with any segment is a multihomed leaf.
MPLS: LDP and L3VPN¶
A provider router runs LDP for its label distribution: one instance per device under the device's Routing tab, with the router ID, an optional transport address (blank = the router ID), whether to allocate labels for host routes only (all an L3VPN needs, and a far smaller label table) or every route, and the interfaces LDP speaks on. LDP has no VRF - labels are for the global table.
The VPN side of an L3VPN sits on the customer VRF's own BGP instance:
Export to VPN / Import from VPN, a label export (auto or a
number) and a next-hop export address. The RD and the route targets
come from the VRF, so nothing is typed twice, and
the vpnv4-unicast family on the PE's global instance carries the routes
to the other PEs. The FRR template prints all
of it.
Routing on virtual machines¶
A virtual router, a firewall VM or a route server runs the same routing a hardware box does, so a virtual machine gets a Routing tab too. Static routes, BGP, OSPF, IS-IS and EIGRP work there exactly as on a device:
- Every static route and protocol instance runs on a device or a virtual machine - one of the two, never both. The form asks which, and opening it from the box's own Routing tab sets it for you.
- Ports and addresses come from the same box. A VM's route, unnumbered BGP session or IGP interface points at one of the VM's interfaces; a session's local address must be assigned to that VM.
- The uniqueness rules are the same per box: one BGP instance per VM and table, one OSPF process per VM, table and version, and so on.
- Site scoping follows the VM's site. A VM with no site is shared, like the VM itself: site-scoped users can see its routing but not change it.
- A VM's config template gets the same
routingblock as a device's, built from the VM's rows. The fabric parts stay empty for a VM: VTEP and LDP are device-only, and so are first-hop groups and Ethernet segments. - Deleting the VM deletes its routing, as deleting a device does.
BGP sessions to or from a VM do not draw on the topology map, which shows devices only.
Rendering a config¶
Every device's and virtual machine's render context carries a routing block, alongside device,
interfaces and ip_addresses (see export templates
for the address filters that turn an address into a mask or a length):
routing:
vrfs: [{name, rd, import_targets, export_targets, l3vni, description}]
static_routes: [{vrf, prefix, kind, next_hop, next_hop_interface, next_hop_vrf,
distance, metric, tag, bfd, description}]
bgp: [{vrf, asn, router_id, cluster_id, graceful_restart, bfd,
address_families: [{afi_safi, networks, maximum_paths, maximum_paths_ibgp,
import_policy, export_policy, redistribute: [{source, policy, metric}]}],
sessions: [{name, peer_group, remote_asn, remote_asn_mode, kind, local_asn,
local_address: {address, cidr, interface}, remote_address, interface,
peer_device, address_families, import_policy, export_policy, bfd,
ebgp_multihop, update_source, next_hop_self, route_reflector_client,
send_community, keepalive, hold_time, keychain, default_originate,
maximum_prefix, allowas_in, as_override, remove_private_as,
soft_reconfiguration, extra}],
peer_groups: [{name, ...}]}] # only the groups this instance's sessions use
ospf: [{vrf, process_id, version, router_id, reference_bandwidth, passive_by_default,
default_originate, bfd, redistribute: [...],
areas: [{area_id, name, kind}],
interfaces: [{interface, area, cost, network_type, passive, priority, hello, dead,
bfd, mtu_ignore, authentication, keychain}]}]
isis: [{vrf, process, net, router_id, level, metric_style, bfd, authentication, keychain,
redistribute: [...],
interfaces: [{interface, families, level, metric, metric_l2, network_type, passive,
hello_interval, hello_multiplier, bfd, authentication, keychain}]}]
eigrp: [{vrf, asn, name, router_id, k_values, variance, maximum_paths, passive_by_default,
stub, bfd, redistribute: [...],
interfaces: [{interface, passive, hello_interval, hold_time, bandwidth_percent,
split_horizon, summary_addresses, bfd, authentication, keychain}]}]
by_interface: {NAME: {vrf, ospf: {process_id, version, area, cost, ...} | null,
isis: {process, families, level, metric, ...} | null,
eigrp: {asn, name, passive, summary_addresses, ...} | null,
fhrp: [{protocol, group_id, name, virtual_ip, cidr, priority}],
gateway: "10.100.0.1/24" | null}}
vtep: {source_interface, source_ip, anycast_ip, anycast_gateway_mac, arp_suppression,
vnis: [{vni, name, kind: l2|l3, vlan, vlan_name, vrf, rd, import_targets,
export_targets, ingress_replication, mcast_group, extra}]} | null
policies: {NAME: {rules: [{sequence, action, match: {...}, set: {...}, continue}]}}
prefix_lists: {NAME: {family, rules: [{sequence, action, prefix, ge, le}]}}
community_lists: {NAME: {kind, rules: [...]}}
as_path_lists: {NAME: {rules: [{sequence, action, regex}]}}
communities: [{value, kind, name}]
keychains: [{name, algorithm, key_set}]
bfd_profiles: [{name, min_tx, min_rx, multiplier, echo}]
keychain_by_name, bfd_profile_by_name: the same two, keyed by name
An l2vpn-evpn address family carries advertise_ipv4_unicast and
advertise_ipv6_unicast (the type-5 leak of a VRF's unicast routes into
EVPN) and, ready to print, advertise: ["ipv4 unicast", …]. An SVI's
by_interface row carries gateway (the anycast address with its mask) and
nd (ra, ra_interval, prefix) from its anycast group.
Wherever a block carries bfd, it carries bfd_profile beside it - the
resolved profile's name, or null for the platform default. by_interface
also carries the port's first-hop groups (fhrp) and, as gateway, the
EVPN anycast gateway's address with its mask - so an SVI loop prints
ip address 10.100.0.1/24 and fabric forwarding mode anycast-gateway
without a template walking the FHRP tables.
vrfs is every table the device has to define - the VRFs its interfaces,
routes and instances sit in, and the VRFs of the L3VNIs its VTEP carries,
each with its l3vni. vtep.vnis is sorted L2 first, then by VNI, with
the VLAN resolved for this leaf. policies and the three list kinds hold only
what the device's address families, sessions and peer groups reference, so
a template prints what the box needs and no more. Session values are the
effective ones; remote_asn_mode is asn, external or internal. Every row carries its
id; vrf is a name, null for the global table.
A static-routes fragment, IOS-style:
{% for r in routing.static_routes %}
ip route {% if r.vrf %}vrf {{ r.vrf }} {% endif %}{{ r.prefix | host }} {{ r.prefix | netmask }} {{ r.next_hop or r.next_hop_interface }}{% if r.distance %} {{ r.distance }}{% endif %}
{% endfor %}
and FRR:
{% for r in routing.static_routes %}
ip route {{ r.prefix }} {{ r.next_hop or r.next_hop_interface }}{% if r.vrf %} vrf {{ r.vrf }}{% endif %}{% if r.distance %} {{ r.distance }}{% endif %}
{% endfor %}
by_interface is what an interfaces loop reaches for - the IGP rows keyed
by port name, so interface swp1 prints its ip ospf area line without a
nested search. An interface's passive is already resolved against the
instance default; an IS-IS row's level is the instance's when the row
left it blank.
An interfaces loop with the IGP lines, FRR-style:
{% for i in interfaces %}
{% set r = routing.by_interface[i.name] %}
interface {{ i.name }}
{% for ip in ip_addresses if ip.assigned_interface_id == i.id %}
ip address {{ ip | cidr }}
{% endfor %}
{% if r and r.ospf %}
ip ospf area {{ r.ospf.area }}
{% if r.ospf.network_type %}
ip ospf network {{ r.ospf.network_type }}
{% endif %}
{% if r.ospf.cost %}
ip ospf cost {{ r.ospf.cost }}
{% endif %}
{% endif %}
{% if r and r.isis %}
{% for fam in r.isis.families %}
{{ 'ip' if fam == 'ipv4' else 'ipv6' }} router isis {{ r.isis.process }}
{% endfor %}
{% if r.isis.network_type == 'point-to-point' %}
isis network point-to-point
{% endif %}
{% endif %}
{% endfor %}
{% for o in routing.ospf %}
router ospf{% if o.vrf %} vrf {{ o.vrf }}{% endif %}
{% if o.router_id %}
ospf router-id {{ o.router_id }}
{% endif %}
{% for iface in o.interfaces if iface.passive %}
passive-interface {{ iface.interface }}
{% endfor %}
{% endfor %}
{% for s in routing.isis %}
router isis {{ s.process }}
net {{ s.net }}
is-type level-{{ s.level }}
metric-style {{ s.metric_style }}
{% endfor %}
A BGP block, FRR-style, with the neighbours' effective values:
{% for b in routing.bgp %}
router bgp {{ b.asn }}{% if b.vrf %} vrf {{ b.vrf }}{% endif %}
{% if b.router_id %}
bgp router-id {{ b.router_id }}
{% endif %}
{% for s in b.sessions %}
{% set n = s.remote_address or s.interface %}
neighbor {{ n }} {% if s.interface %}interface {% endif %}remote-as {{ s.remote_asn if s.remote_asn_mode == 'asn' else s.remote_asn_mode }}
{% if s.update_source %}
neighbor {{ n }} update-source {{ s.update_source }}
{% endif %}
{% if s.bfd %}
neighbor {{ n }} bfd
{% endif %}
{% endfor %}
{% for af in b.address_families %}
address-family {{ af.afi_safi.replace('-', ' ') }}
{% for net in af.networks %}
network {{ net }}
{% endfor %}
{% for s in b.sessions if af.afi_safi in s.address_families %}
neighbor {{ s.remote_address or s.interface }} activate
{% if s.route_reflector_client %}
neighbor {{ s.remote_address or s.interface }} route-reflector-client
{% endif %}
{% endfor %}
exit-address-family
{% endfor %}
{% endfor %}
An NX-OS-style VTEP fragment:
{% if routing.vtep %}
interface nve1
source-interface {{ routing.vtep.source_interface }}
host-reachability protocol bgp
{% for v in routing.vtep.vnis %}
member vni {{ v.vni }}{% if v.kind == "l3" %} associate-vrf{% elif v.ingress_replication %}
ingress-replication protocol bgp{% else %}
mcast-group {{ v.mcast_group }}{% endif %}
{% endfor %}
{% for v in routing.vtep.vnis if v.vlan %}
vlan {{ v.vlan }}
vn-segment {{ v.vni }}
{% endfor %}
{% endif %}
The same block rides the Ansible inventory as danbyte.routing - always on
a single host (GET /api/devices/<id>/inventory/), on the fleet export when
asked (GET /api/inventory/ansible/?routing=1), since most plays never read
it.
API¶
| Endpoint | Purpose |
|---|---|
/api/routing/prefix-lists/, …/community-lists/, …/as-path-lists/, …/policies/ |
The lists, rules nested; write rules: [...] to replace the set. |
…/prefix-list-rules/, …/community-list-rules/, …/as-path-list-rules/, …/policy-rules/ |
Rule rows on their own, filtered by their list (?prefix_list=, ?policy=, …). |
/api/routing/communities/ |
Communities. |
/api/routing/keychains/ |
Keychains; psk is write-only, reveal-psk is the audited read. |
/api/routing/bfd-profiles/ |
BFD profiles; every instance, enrolled interface, session and peer group takes bfd_profile_id. |
/api/routing/static-routes/ |
Static routes; filter by device, virtual_machine, vrf (global for the global table), kind, status, site, prefix_obj. |
/api/routing/bgp-instances/ |
Instances with their address families nested; filter by device, virtual_machine, vrf, asn, site, status. |
/api/routing/bgp-address-families/, …/redistributions/ |
The rows on their own (?instance=, ?bgp_af=, ?ospf_instance=, ?isis_instance=, ?eigrp_instance=); an address family or IGP instance accepts redistributions: [...]. |
/api/routing/bgp-peer-groups/ |
Peer groups. |
/api/routing/bgp-sessions/ |
Sessions with effective; filter by device, virtual_machine, instance, vrf (global), site, asn, remote_asn, peer_group, peer_device, status, af. POST …/<id>/create-peer/ writes the mirror session. |
/api/routing/ospf-areas/ |
Areas. |
/api/routing/ospf-instances/, …/isis-instances/ |
Instances with their interfaces and redistributions nested; accept redistributions: [...]; filter by device, virtual_machine, vrf, site, status. |
/api/routing/ospf-interfaces/, …/isis-interfaces/ |
Enrolled interfaces (?instance=, ?interface=, ?area=). |
/api/routing/eigrp-instances/, …/eigrp-interfaces/ |
EIGRP instances (interfaces and redistributions nested; filter by device, virtual_machine, vrf, site, status) and their enrolled interfaces (?instance=, ?interface=). |
/api/routing/vteps/ |
One per device, VNI memberships nested; filter by device, site, status, l2vpn. |
/api/routing/vtep-memberships/ |
The VNI rows on their own (?vtep=, ?l2vpn=). |
/api/l2vpns/ |
Gains vrf/vrf_id and vtep_count; ?vxlan=1 keeps the VXLAN types, ?vrf= the L3VNIs of a VRF, ?vlan= those terminating on a VLAN. |
Child rows - address families, OSPF, IS-IS and EIGRP interface rows, VTEP
memberships - carry their parent read-only on their own endpoints
(instance or vtep: id, device or virtual machine, and the process or
ASN), so a sync can
tell from the collection which parent a row is under; instance_id /
vtep_id stay the write side.
A row on a virtual machine is written with virtual_machine_id in place of
device_id, and its ports with vm_interface_id (sessions and IGP
interfaces) or next_hop_vm_interface_id (static routes). Reads carry both
device and virtual_machine, one of them null, plus site.
Every list takes ?picker=1 for the compact row shape, ?search=, and
supports CSV import/export and bulk delete like the rest of Danbyte. A CSV
row without an id is matched on what makes it unique - a static route by
device, prefix and next hop, a BGP instance by device and VRF, a session by
instance and remote address, an OSPF or IS-IS instance by device and
process, a VTEP by its device; catalogs by name. Rows on a virtual machine
match on their id. An ASN is written as its number.
The routing that touches an object shows on that object's page: a device's Routing tab, an interface's Routing card, an ASN's BGP sessions tab, a peer group's Sessions tab, a VRF's BGP sessions and Static routes tabs, a prefix's Static routes tab (routes with that prefix as their destination), an L2VPN's VTEPs tab and a VLAN's L2VPNs tab.
The Routing menu is grouped by protocol: BGP (instances, sessions, peer groups), OSPF (instances, areas), IS-IS, EIGRP, EVPN / VXLAN (VTEPs), Static (static routes), Policy (routing policies, prefix lists, communities, community lists, AS-path lists) and Profiles (keychains, BFD profiles). An instance or a VTEP is added and edited on its device's Routing tab - the fleet list is where you find which boxes run what, and its pencil takes you there. A list's rules (prefix lists, community lists, AS-path lists, policies) are edited on the list's edit page; the Rules tab links to it.
Permissions and audit¶
Each routing object is its own RBAC type under the Routing group; a site-scoped grant on static routes covers the routes of that site's devices. Every create, edit and delete - rule rows included - is in the change log.