{
    "product": "Cenvero Stratum",
    "generated_at": "2026-08-03T07:18:25+00:00",
    "format": "cenvero-docs-v1",
    "document_count": 1,
    "documents": [
        {
            "slug": "networking/bgp",
            "title": "BGP Edge Routing",
            "category": "Networking",
            "url": "https://www.stratum.cenvero.com/docs/networking/bgp",
            "headings": [
                {
                    "level": 1,
                    "text": "BGP Edge Routing"
                },
                {
                    "level": 2,
                    "text": "How it fits together"
                },
                {
                    "level": 3,
                    "text": "What travels in each direction"
                },
                {
                    "level": 3,
                    "text": "How a session comes up"
                },
                {
                    "level": 2,
                    "text": "Configuring a peer session"
                },
                {
                    "level": 2,
                    "text": "Announcing prefixes"
                },
                {
                    "level": 2,
                    "text": "Importing external prefixes"
                },
                {
                    "level": 2,
                    "text": "Checking RIB and FIB"
                },
                {
                    "level": 2,
                    "text": "RPKI route-origin validation"
                },
                {
                    "level": 2,
                    "text": "EVPN address family"
                },
                {
                    "level": 2,
                    "text": "See also"
                }
            ],
            "word_count": 1597,
            "markdown": "# BGP Edge Routing\n\nGateway nodes run an integrated BGP speaker that connects your fabric to the outside world. You configure peer sessions, announce your managed-network prefixes upstream, optionally import external routes, and filter routes with prefix-lists and route-maps — all through `cenvero-str-ctl`.\n\n## How it fits together\n\nA node at the edge of the fabric speaks BGP upstream. It speaks eBGP to one or more upstream routers or route reflectors, announcing the subnets of your internal networks so external hosts can reach them. Inbound prefixes learned from peers are installed into the kernel routing table and become reachable from within the fabric.\n\n### What travels in each direction\n\nTwo separate flows, and confusing them is the usual cause of \"the session is up\nbut nothing works\":\n\n**Out — what you announce.** Nothing leaves automatically. A prefix is advertised\nonly once you announce it, so bringing a session up publishes nothing on its own.\nUntil you announce, your peer has no idea your networks exist and traffic will not\ncome to you.\n\n**In — what you learn.** Prefixes your peers advertise are accepted, subject to\nany filters you set, and installed as routes so workloads inside the fabric can\nreach them. A peer that sends you nothing leaves you with a working session and\nno new routes, which is normal if it is only meant to receive.\n\nA session being **Established** means the two speakers are talking. It does not\nmean any route has been exchanged in either direction — check what is actually\nbeing carried rather than inferring it from the session state.\n\n### How a session comes up\n\nA peer moves through a sequence of states, and knowing them makes the difference\nbetween waiting and debugging:\n\n| State | Meaning |\n|---|---|\n| **Idle** | Not trying yet, or backing off after a failure before the next attempt. |\n| **Connect** / **Active** | Trying to reach the peer. Sitting here means the peer is not answering — check reachability and that it is expecting you. |\n| **OpenSent** / **OpenConfirm** | Connected; the two sides are agreeing terms. Sitting here usually means a mismatch, most often the AS number each side expects of the other. |\n| **Established** | Working. Routes can now be exchanged. |\n\nBoth ends may try to connect to each other at the same time — normal when two\nStratum nodes peer directly. Two connections briefly exist and one is discarded\nautomatically, which is expected and needs no configuration.\n\nOnce established, the two exchange keepalives (every 30 seconds by default). If\nnothing is heard for the hold time (90 seconds by default) the session is\nconsidered dead and torn down, and the routes learned through it are withdrawn.\nLower both if you need failure detected faster, at the cost of more chatter —\nthey are negotiated, so the peer must agree.\n\n> Peers that keep returning to Idle are usually being rejected rather than\n> failing to connect. Check the AS numbers on both sides first; that is the most\n> common cause.\n\nFor redundant deployments with a pair of Gateways, both nodes can establish their own peer sessions and announce the fabric prefixes. The shared VIP is held by exactly one Gateway at a time (priority-based active/standby); Stratum's HA mechanism moves the VIP to the surviving node if the active Gateway goes down. See [Gateway High Availability](/docs/clustering/high-availability).\n\n## Configuring a peer session\n\n```bash\nsudo cenvero-str-ctl bgp peer add '{\"peer_addr\":\"198.51.100.1\",\"peer_as\":65001,\"local_as\":65100,\"md5_key\":\"mysecretpass\"}'\n```\n\nThe neighbour is a single JSON object. `peer_addr`, `peer_as`, and `local_as` are required; the rest are optional:\n\n| Field | Description |\n|-------|-------------|\n| `peer_addr` | Upstream router's IP address |\n| `peer_as` | Upstream router's AS number |\n| `local_as` | This node's AS number |\n| `md5_key` | BGP TCP-MD5 authentication key (optional but recommended; never returned in reads) |\n| `hold_time` | BGP hold timer in seconds (default `90`) |\n| `keepalive_interval` | BGP keepalive interval in seconds (default `30`) |\n| `bfd_enabled` | Enable BFD fast failure detection for this peer (`true`/`false`) |\n| `bfd_interval_ms` | BFD min-tx/min-rx interval in milliseconds |\n| `bfd_multiplier` | BFD detect multiplier (failure-detection time is interval × multiplier) |\n\nList configured peers and their session state:\n\n```bash\ncenvero-str-ctl bgp peer list\n```\n\n```text\nPEER            PEER-ASN  LOCAL-ASN  STATE        PREFIXES-RX  PREFIXES-TX\n198.51.100.1    65001     65100      Established  12           3\n198.51.100.2    65002     65100      Established  8            3\n```\n\nRemove a peer session:\n\n```bash\nsudo cenvero-str-ctl bgp peer remove 198.51.100.1\n```\n\n## Announcing prefixes\n\nTell Stratum which internal prefixes to advertise to peers:\n\n```bash\nsudo cenvero-str-ctl bgp announce 10.20.0.0/24\nsudo cenvero-str-ctl bgp announce 10.30.0.0/24\n```\n\nAnnouncements take effect as soon as they are added. You can also announce a summary prefix that covers multiple networks:\n\n```bash\nsudo cenvero-str-ctl bgp announce 10.20.0.0/20\n```\n\nList what you are announcing:\n\n```bash\ncenvero-str-ctl bgp announcements\n```\n\nWithdraw a prefix (peers are notified immediately):\n\n```bash\nsudo cenvero-str-ctl bgp withdraw 10.20.0.0/24\n```\n\n## Importing external prefixes\n\nBy default, prefixes learned from peers are installed in the kernel routing table and are reachable from within the fabric. You can filter what gets imported.\n\nFiltering is expressed as **prefix-lists** and **route-maps**, then bound to a neighbour as an import (or export) policy — each is a single JSON object. First define a prefix-list of the CIDRs you care about (entries are matched in order; each has an `action` of `allow` or `deny` and optional `ge`/`le` length bounds):\n\n```bash\nsudo cenvero-str-ctl bgp prefix-list add '{\"name\":\"customer-routes\",\"entries\":[{\"prefix\":\"172.16.0.0/12\",\"action\":\"allow\",\"le\":24},{\"prefix\":\"0.0.0.0/0\",\"action\":\"deny\"}]}'\n```\n\nReference that prefix-list from a route-map, which decides what to do with a matching route and can set attributes such as local-preference:\n\n```bash\nsudo cenvero-str-ctl bgp route-map add '{\"name\":\"import-filter\",\"entries\":[{\"seq\":10,\"action\":\"allow\",\"match_prefix\":\"customer-routes\",\"set_local_pref\":200}]}'\n```\n\nBind the route-map to a neighbour as its import policy (use `export` for the outbound direction):\n\n```bash\nsudo cenvero-str-ctl bgp policy import 198.51.100.1 import-filter\n```\n\n## Checking RIB and FIB\n\nInspect the BGP routing information base:\n\n```bash\ncenvero-str-ctl bgp rib\n```\n\n```text\nPREFIX            NEXT-HOP       AS-PATH    MED  LOCAL-PREF  SOURCE\n10.20.0.0/24      0.0.0.0        -          -    -           local\n0.0.0.0/0         198.51.100.1   65001      0    100         ebgp\n172.16.0.0/12     198.51.100.1   65001      0    100         ebgp\n```\n\nShow only routes installed in the kernel forwarding table:\n\n```bash\ncenvero-str-ctl bgp fib\n```\n\n## RPKI route-origin validation\n\nRoute-Origin Validation (ROV, RFC 6811) checks each prefix a peer advertises against Resource Public Key Infrastructure (RPKI) data, so you can tell whether the AS that originated a route is actually authorized to announce it. Stratum learns the set of validated prefix-to-origin records (the VRP set) from an external RPKI-to-Router (RTR, RFC 8210) cache — such as Routinator, rpki-client, or StayRTR — and classifies every received route as:\n\n- **valid** — a matching record authorizes this prefix from this origin AS.\n- **invalid** — a record covers the prefix but the origin AS or prefix length does not match, a likely mis-origination or hijack.\n- **not-found** — no record covers the prefix.\n\nROV is **off by default and fail-safe.** With no RTR configured, an unreachable cache, or stale data, the VRP set is empty, every route resolves to *not-found*, and BGP behaves exactly as it would without ROV — an RTR outage can never cause a route to be rejected. By default ROV only **marks** each route with its validation state and does not change route selection; the opt-in reject-invalid policy additionally drops RPKI-invalid routes before they enter the routing table.\n\nPoint Stratum at your RTR cache and start validating:\n\n```bash\nsudo cenvero-str-ctl bgp rpki configure 192.0.2.10:323 --reject-invalid\n```\n\n| Argument / flag | Description |\n|-----------------|-------------|\n| `<rtr-addr>` | Address (`host:port`) of the RTR cache to connect to |\n| `--reject-invalid` | Drop RPKI-invalid routes instead of only marking them (optional) |\n\nCheck the RTR session state, VRP count, and per-outcome validation tallies:\n\n```bash\ncenvero-str-ctl bgp rpki status\n```\n\nTest how a given prefix and origin AS would classify against the current VRP set:\n\n```bash\ncenvero-str-ctl bgp rpki validate 192.0.2.0/24 64500\n```\n\nStart or stop ROV using the configured RTR address; disabling clears the VRP set and reverts to plain BGP:\n\n```bash\nsudo cenvero-str-ctl bgp rpki enable\nsudo cenvero-str-ctl bgp rpki disable\n```\n\n## EVPN address family\n\nStratum's BGP speaker can carry the **EVPN** (Ethernet VPN, RFC 7432) address family — L2VPN/EVPN over MP-BGP — integrated with the VXLAN overlay (EVPN-VXLAN, RFC 8365). It exchanges two route types with EVPN-capable peers:\n\n- **Type 2 (MAC/IP)** — advertises the MAC (and optional IP) of a local overlay endpoint, so peers learn which VTEP a MAC lives behind.\n- **Type 3 (Inclusive Multicast)** — advertises the local VTEP so peers know where to send broadcast, unknown-unicast, and multicast traffic for a VNI.\n\nEach route carries a Route Distinguisher and Route Target, and the 24-bit VXLAN VNI is encoded in the MPLS label field.\n\n> **Scope — control plane only.** EVPN in Stratum is a route-exchange feature: it learns remote MAC-to-VTEP and VTEP bindings over BGP and maintains the EVPN route tables, but it does not program those learned routes into the overlay forwarding path. Use it to exchange and inspect MAC/VTEP reachability, and configure VXLAN peers explicitly for forwarding (see [Clustering Overview](/docs/clustering/overview)).\n\nEVPN is **off by default** and backward-compatible: while disabled, the EVPN address family is not advertised and BGP behaves exactly like the plain IPv4/IPv6-unicast speaker.\n\nEnable EVPN, advertising a local VTEP and route distinguisher:\n\n```bash\nsudo cenvero-str-ctl bgp evpn enable --vtep 10.0.0.1 --rd 65000:100\n```\n\n| Flag | Description |\n|------|-------------|\n| `--vtep` | Local VTEP source IP advertised as the EVPN next hop |\n| `--rd` | Route distinguisher, e.g. `65000:100` or `10.0.0.1:100` |\n\nRegister a local MAC (and optional IP) under a VNI so it is advertised as a Type 2 route:\n\n```bash\nsudo cenvero-str-ctl bgp evpn local-mac add 10100 aa:bb:cc:dd:ee:ff 192.0.2.10\n```\n\nInspect EVPN state and the local plus learned routes:\n\n```bash\ncenvero-str-ctl bgp evpn status\ncenvero-str-ctl bgp evpn show\n```\n\nDisable EVPN — it stops advertising the address family and withdraws the routes it announced:\n\n```bash\nsudo cenvero-str-ctl bgp evpn disable\n```\n\n## See also\n\n- [Gateway High Availability](/docs/clustering/high-availability) — redundant Gateway BGP speakers and failover.\n- [Load Balancer](/docs/networking/load-balancer) — combine BGP with L4 VIPs for published external services.\n- [Zero-Trust Firewall](/docs/networking/firewall) — north-south traffic from BGP peers passes through the firewall.\n"
        }
    ]
}