Skip to content

Add External API endpoints for BGP unnumbered interface manager status#10705

Open
taspelund wants to merge 3 commits into
mainfrom
trey/bgp-unnumbered-status
Open

Add External API endpoints for BGP unnumbered interface manager status#10705
taspelund wants to merge 3 commits into
mainfrom
trey/bgp-unnumbered-status

Conversation

@taspelund

Copy link
Copy Markdown
Contributor

This is the omicron side of maghemite#800.

In mgd, we are refactoring the internals of BGP unnumbered which affects the mg-api by no longer requiring the BGP ASN for querying the state... However, omicron never had plumbing to query BGP unnumbered interface state to begin with, which is what this PR remedies.

The new API endpoints are purely status, with no config whatsoever.

The maghemite hash currently points to the feature branch, but will be updated to main once this PR's counterpart lands.

Now that maghemite has migrated to the RFD 619 convention, it exposes
most types via the mg-api-types crate. This crate should have its hash
updated alongside mg-admin-client and ddm-admin-client.

Signed-off-by: Trey Aspelund <trey@oxidecomputer.com>
@taspelund taspelund self-assigned this Jul 1, 2026
@taspelund taspelund added enhancement New feature or request. api Related to the API. networking Related to the networking. rust Pull requests that update rust code labels Jul 1, 2026
@taspelund

Copy link
Copy Markdown
Contributor Author

I have taken this through a4x2 manually and have validated that e2e connectivity works, as do the new endpoints:

trey@korgano 03:21:19 AM | ~/git/omicron ➦ d372d6342 ○
‣ curl -sS "${AUTH[@]}" "http://198.51.100.24/v1/system/networking/bgp/unnumbered/manager" | jq
[
  {
    "switch_slot": "switch0",
    "state": {
      "monitor_running": true,
      "pending_interfaces": [],
      "active_interfaces": [
        "qsfp0",
        "qsfp1"
      ]
    }
  },
  {
    "switch_slot": "switch1",
    "state": {
      "monitor_running": true,
      "pending_interfaces": [],
      "active_interfaces": [
        "qsfp1",
        "qsfp0"
      ]
    }
  }
]

trey@korgano 03:21:22 AM | ~/git/omicron ➦ d372d6342 ○
‣ curl -sS "${AUTH[@]}" "http://198.51.100.24/v1/system/networking/bgp/unnumbered/interfaces" | jq
[
  {
    "switch_slot": "switch0",
    "interface": {
      "interface": "qsfp0",
      "local_address": "fe80::aa40:25ff:fe25:9735",
      "router_lifetime": 1800,
      "discovered_peer": {
        "address": "fe80::aa40:25ff:fe00:9",
        "discovered_at": "2026-07-01T00:28:26Z",
        "last_advertisement": "2026-07-01T03:23:15Z",
        "router_lifetime": 30,
        "reachable_time": 0,
        "retrans_timer": 0,
        "expired": false,
        "time_until_expiry": "9s 61ms"
      },
      "ndp_state": {
        "tx": true,
        "rx": true
      }
    }
  },
  {
    "switch_slot": "switch0",
    "interface": {
      "interface": "qsfp1",
      "local_address": "fe80::aa40:25ff:fe25:9739",
      "router_lifetime": 1800,
      "discovered_peer": {
        "address": "fe80::aa40:25ff:fe00:11",
        "discovered_at": "2026-07-01T00:28:26Z",
        "last_advertisement": "2026-07-01T03:23:15Z",
        "router_lifetime": 30,
        "reachable_time": 0,
        "retrans_timer": 0,
        "expired": false,
        "time_until_expiry": "9s 398ms"
      },
      "ndp_state": {
        "tx": true,
        "rx": true
      }
    }
  },
  {
    "switch_slot": "switch1",
    "interface": {
      "interface": "qsfp1",
      "local_address": "fe80::aa40:25ff:fe4f:cc12",
      "router_lifetime": 1800,
      "discovered_peer": {
        "address": "fe80::aa40:25ff:fe00:12",
        "discovered_at": "2026-07-01T00:24:15Z",
        "last_advertisement": "2026-07-01T03:23:16Z",
        "router_lifetime": 30,
        "reachable_time": 0,
        "retrans_timer": 0,
        "expired": false,
        "time_until_expiry": "9s 550ms"
      },
      "ndp_state": {
        "tx": true,
        "rx": true
      }
    }
  },
  {
    "switch_slot": "switch1",
    "interface": {
      "interface": "qsfp0",
      "local_address": "fe80::aa40:25ff:fe4f:cc0e",
      "router_lifetime": 1800,
      "discovered_peer": {
        "address": "fe80::aa40:25ff:fe00:10",
        "discovered_at": "2026-07-01T00:24:15Z",
        "last_advertisement": "2026-07-01T03:23:16Z",
        "router_lifetime": 30,
        "reachable_time": 0,
        "retrans_timer": 0,
        "expired": false,
        "time_until_expiry": "9s 549ms"
      },
      "ndp_state": {
        "tx": true,
        "rx": true
      }
    }
  }
]

trey@korgano 03:24:15 AM | ~/git/omicron ➦ d372d6342 ○
‣ curl -sS "${AUTH[@]}" "http://198.51.100.24/v1/system/networking/bgp/unnumbered/interfaces/switch0/qsfp0" | jq
{
  "switch_slot": "switch0",
  "interface": {
    "interface": "qsfp0",
    "local_address": "fe80::aa40:25ff:fe25:9735",
    "router_lifetime": 1800,
    "discovered_peer": {
      "address": "fe80::aa40:25ff:fe00:9",
      "discovered_at": "2026-07-01T00:28:26Z",
      "last_advertisement": "2026-07-01T03:27:15Z",
      "router_lifetime": 30,
      "reachable_time": 0,
      "retrans_timer": 0,
      "expired": false,
      "time_until_expiry": "9s 260ms"
    },
    "ndp_state": {
      "tx": true,
      "rx": true
    }
  }
}

Adds external API endpoints to GET the BGP unnumbered status of
interfaces and the unnumbered manager. This provides insights into the
Router Discovery state (have we learned about a BGP peer via NDP) and
the readiness of an interface that's been configured for BGP unnumbered
(does the interface exist in the OS? does it have an IPv6 link-local IP?
or is it active?). These are all important when diagnosing failures or
delays in the establishment of BGP unnumbered peers, since these are all
prerequisites for the BGP FSM to complete connections.

This is the omicron side of maghemite#800

Signed-off-by: Trey Aspelund <trey@oxidecomputer.com>
Signed-off-by: Trey Aspelund <trey@oxidecomputer.com>
@taspelund taspelund force-pushed the trey/bgp-unnumbered-status branch from 4736713 to 654fe27 Compare July 1, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the API. enhancement New feature or request. networking Related to the networking. rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant