diff --git a/crates/web/static/statusz.html b/crates/web/static/statusz.html
index 5b53fd1..bc7f4dd 100644
--- a/crates/web/static/statusz.html
+++ b/crates/web/static/statusz.html
@@ -412,6 +412,17 @@ from
return p.state === 'Established' && p.expected_routes > 0 && p.routes != null
&& p.routes < p.expected_routes / 2 && now() - p.established_at_unix > SETTLING_SECS;
}
+ // Peers in name order, except that the IPv6 session of a neighbour
+ // (-v6) comes before its IPv4 one: IPv6 is the network's present,
+ // IPv4 what is still carried along.
+ const FAMILY_SUFFIX = /^(.*)-v([46])$/;
+ function nameOrder(a, c) {
+ const [sa, fa] = FAMILY_SUFFIX.exec(a)?.slice(1) || [a, ''];
+ const [sc, fc] = FAMILY_SUFFIX.exec(c)?.slice(1) || [c, ''];
+ return sa.localeCompare(sc) || fc.localeCompare(fa);
+ }
+ const byName = (a, c) => nameOrder(a.name || a.peer_addr, c.name || c.peer_addr);
+
// Where a peer stands, for the strip and for sorting: 0 failed, 1
// degraded, 2 normal, 3 inactive and expected.
function peerRank(p) {
@@ -524,9 +535,8 @@ from
if (!peers.length) { setHTML(b, '
No peers configured and none connected.
'); return; }
const problemsOnly = $('peers-problems').checked;
// The IPv4 and IPv6 sessions of one neighbour, named -v4 and
- // -v6, are one neighbour to the reader: listed together, the
- // name once in full and once quietly, joined down the side.
- const FAMILY_SUFFIX = /^(.*)-v([46])$/;
+ // -v6, are one neighbour to the reader: listed together, IPv6
+ // first, the name once in full and once quietly, joined down the side.
const row = (p, pair) => {
const up = p.state === 'Established';
const family = p.name && FAMILY_SUFFIX.exec(p.name);
@@ -559,7 +569,6 @@ from
if (sameStem(list[i - 1])) return row(p, 'pair-b');
return row(p);
}).join('');
- const byName = (a, c) => (a.name || a.peer_addr).localeCompare(c.name || c.peer_addr);
let html = '';
// What needs attention first, whoever it is; then everyone by what
// they are to us.
@@ -661,7 +670,7 @@ from
function renderPeerChoices() {
const chosen = lookup().peer;
const names = [...new Set(state.peers.filter(p => p.state === 'Established')
- .map(p => p.name || p.peer_addr.replace(/:\d+$/, '').replace(/^\[|\]$/g, '')))].sort();
+ .map(p => p.name || p.peer_addr.replace(/:\d+$/, '').replace(/^\[|\]$/g, '')))].sort(nameOrder);
if (chosen && !names.includes(chosen)) names.push(chosen);
setHTML($('lookup-peer'), '' +
names.map(n => ``).join(''));
diff --git a/docs/content/docs/operations/monitoring.md b/docs/content/docs/operations/monitoring.md
index 637ae78..662d1b6 100644
--- a/docs/content/docs/operations/monitoring.md
+++ b/docs/content/docs/operations/monitoring.md
@@ -40,8 +40,8 @@ Below the status line, the page displays the following information:
session properties, number of accepted routes, rejected announcements,
and held routes, and its last error. Neighbors that need attention are
listed first; the others are grouped by role. The IPv4 and IPv6 sessions
- of one neighbor, named `NAME-v4` and `NAME-v6`, are listed together and
- joined by a bar. The **problems only** option hides the neighbors that
+ of one neighbor, named `NAME-v4` and `NAME-v6`, are listed together,
+ IPv6 first, and joined by a bar. The **problems only** option hides the neighbors that
need no attention; the **compact** option removes the next hop and
session columns, for a small or distant screen, and is remembered by the
browser.