diff --git a/crates/integration-tests/tests/http_api.rs b/crates/integration-tests/tests/http_api.rs
index 4c18cee..fd88d69 100644
--- a/crates/integration-tests/tests/http_api.rs
+++ b/crates/integration-tests/tests/http_api.rs
@@ -113,6 +113,7 @@ async fn test_announce_over_http_reaches_peer() -> Result<()> {
let wire = get_json(&client, &format!("{base}/api/routes/local/wire?prefix=10.100.1.0/24")).await?;
assert_eq!(wire.as_array().unwrap().len(), 1);
assert_eq!(wire[0]["peer_asn"], PEER_ASN);
+ assert_eq!(wire[0]["four_octet_asn"], true);
assert_eq!(wire[0]["summary"]["as_path"], json!([LOCAL_ASN, LOCAL_ASN]));
let hex = wire[0]["hex"].as_str().unwrap();
let ctx = ParserContext { four_octet_asn: peer.ctx.four_octet_asn, address_family: None };
diff --git a/crates/web/src/api.rs b/crates/web/src/api.rs
index 6dc151e..e1dc1fd 100644
--- a/crates/web/src/api.rs
+++ b/crates/web/src/api.rs
@@ -256,6 +256,8 @@ pub struct WireView {
pub peer_addr: String,
pub peer_asn: u32,
pub next_hop: String,
+ /// Whether AS numbers in AS_PATH are 4 bytes wide on this session.
+ pub four_octet_asn: bool,
/// Complete BGP message including the 19-byte header, as lowercase hex.
pub hex: String,
pub length: usize,
@@ -426,6 +428,7 @@ pub async fn wire(
peer_addr: session.peer.addr.to_string(),
peer_asn: session.peer.asn,
next_hop: session.local_addr.ip().to_string(),
+ four_octet_asn: session.four_octet_asn,
hex: buf.iter().map(|b| format!("{b:02x}")).collect(),
length: buf.len(),
summary: summarize(&update.path_attributes),
diff --git a/crates/web/static/statusz.html b/crates/web/static/statusz.html
index afd9c68..2437351 100644
--- a/crates/web/static/statusz.html
+++ b/crates/web/static/statusz.html
@@ -34,6 +34,14 @@ pre.bytes { border: 1px solid #99a; background: #fff; padding: 4px; margin: 4px
.hh { background: #dde; } .hl { background: #fcc; } .ha { background: #cfc; } .ha2 { background: #ada; } .hn { background: #ffc; }
#event-log { font-family: monospace; font-size: 12px; max-height: 22em; overflow-y: auto; }
#event-log div { white-space: pre-wrap; }
+pre.bytes span[data-kind] { cursor: help; }
+pre.bytes span[data-kind]:hover, pre.bytes span[data-kind]:focus { outline: 1px solid #00c; }
+#tip { position: absolute; z-index: 10; max-width: 46em; background: #fff; border: 1px solid #99a; font-size: 12px; }
+#tip .tip-title { background: #eef; font-weight: bold; text-align: center; padding: 1px 6px; border-bottom: 1px solid #99a; }
+#tip table { border-collapse: collapse; }
+#tip td { padding: 1px 6px; vertical-align: top; }
+#tip td:first-child { color: #666; white-space: nowrap; }
+#tip td.mono { word-break: break-word; }
address { font-size: smaller; margin-top: 2em; color: #444; }
@@ -50,7 +58,7 @@ Router ID ..., local AS ...