obmp-docker/exabgp/iosxr_bgp_config.md
sam 233dadbb41 Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
  route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
  full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
  listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
  user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00

4.7 KiB

IOS-XR BGP Config for ExaBGP Peering

Apply to both CORE routers (CML-R9K-CORE-01 @ 10.100.0.100 and CML-R9K-CORE-02 @ 10.100.0.200).

Credentials: ssh user@<mgmt-ip> password cisco


Route Policy (apply once per router)

route-policy EXABGP_IN
  pass
end-policy

route-policy EXABGP_OUT
  drop
end-policy

BGP Neighbor Block

router bgp 65020
 neighbor 10.40.40.202
  remote-as 65100
  description ExaBGP-Route-Injector
  ebgp-multihop 5
  update-source MgmtEth0/RP0/CPU0/0
  !
  address-family ipv4 unicast
   route-policy EXABGP_IN in
   route-policy EXABGP_OUT out
   next-hop-self
  !
  address-family ipv6 unicast
   route-policy EXABGP_IN in
   route-policy EXABGP_OUT out
   next-hop-self
  !
 !
!

Key config notes

Knob Why
remote-as 65100 ExaBGP presents as AS 65100 (eBGP to your AS 65020 mesh)
ebgp-multihop 5 Host (10.40.40.202) and router (10.100.0.x) are different subnets
update-source MgmtEth0/RP0/CPU0/0 Use management interface for the TCP session
next-hop-self Replace ExaBGP's next-hop (10.40.40.202) with the CORE router's loopback when reflecting into iBGP — ensures other routers can resolve the next-hop via ISIS
EXABGP_OUT drops Prevent the lab from advertising its own prefixes back to ExaBGP

Verification Commands

show bgp neighbors 10.40.40.202
show bgp neighbors 10.40.40.202 received routes
show bgp summary
show route 1.1.1.0/24
show bgp 1.1.1.0/24

After loading the internet_sample scenario you should see ~94 new prefixes in the BGP table and they should propagate to all 9 routers via the iBGP mesh.


NETCONF push (alternative to CLI)

With NETCONF already enabled, you can push this config programmatically:

pip install ncclient

python3 - <<'EOF'
from ncclient import manager

ROUTERS = [
    {'host': '10.100.0.100', 'description': 'CML-R9K-CORE-01'},
    {'host': '10.100.0.200', 'description': 'CML-R9K-CORE-02'},
]

POLICY_XML = """
<config>
  <routing-policy xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-policy-repository-cfg">
    <route-policies>
      <route-policy>
        <route-policy-name>EXABGP_IN</route-policy-name>
        <rpl-route-policy>route-policy EXABGP_IN&#10;  pass&#10;end-policy</rpl-route-policy>
      </route-policy>
      <route-policy>
        <route-policy-name>EXABGP_OUT</route-policy-name>
        <rpl-route-policy>route-policy EXABGP_OUT&#10;  drop&#10;end-policy</rpl-route-policy>
      </route-policy>
    </route-policies>
  </routing-policy>
  <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ipv4-bgp-cfg">
    <instance>
      <instance-name>default</instance-name>
      <instance-as>
        <as>0</as>
        <four-byte-as>
          <as>65020</as>
          <bgp-running/>
          <default-vrf>
            <bgp-entity>
              <neighbors>
                <neighbor>
                  <neighbor-address>10.40.40.202</neighbor-address>
                  <remote-as>
                    <as-xx>0</as-xx>
                    <as-yy>65100</as-yy>
                  </remote-as>
                  <description>ExaBGP-Route-Injector</description>
                  <ebgp-multihop>
                    <max-hop-count>5</max-hop-count>
                  </ebgp-multihop>
                  <update-in-filtering>
                    <enable/>
                  </update-in-filtering>
                  <neighbor-afs>
                    <neighbor-af>
                      <af-name>ipv4-unicast</af-name>
                      <activate/>
                      <route-policy-in>EXABGP_IN</route-policy-in>
                      <route-policy-out>EXABGP_OUT</route-policy-out>
                      <next-hop-self>true</next-hop-self>
                    </neighbor-af>
                    <neighbor-af>
                      <af-name>ipv6-unicast</af-name>
                      <activate/>
                      <route-policy-in>EXABGP_IN</route-policy-in>
                      <route-policy-out>EXABGP_OUT</route-policy-out>
                      <next-hop-self>true</next-hop-self>
                    </neighbor-af>
                  </neighbor-afs>
                </neighbor>
              </neighbors>
            </bgp-entity>
          </default-vrf>
        </four-byte-as>
      </instance-as>
    </instance>
  </bgp>
</config>
"""

for router in ROUTERS:
    print(f"Configuring {router['description']} ({router['host']})...")
    with manager.connect(
        host=router['host'],
        port=830,
        username='user',
        password='cisco',
        hostkey_verify=False,
        device_params={'name': 'iosxr'},
    ) as m:
        m.edit_config(target='candidate', config=POLICY_XML)
        m.commit()
    print(f"  Done.")

print("All routers configured.")
EOF