fix(bgp): сохранять неизвестные показатели без вымышленных чисел
This commit is contained in:
1 parent
c557a8c8cb
commit
9fbe27c1b0
12 files changed
+1168
-49
No files matched your search
@@ -6,7 +6,9 @@ const raw = { ".id": "*1", "total-updates-received": "42", "total-updates-sent":
|
||||
const missing = parseBgpCatalogSessions(server, [raw])[0]
|
||||
assert.equal(missing.state, "Unknown")
|
||||
for (const field of ["prefixesRx", "prefixesTx", "holdTime", "keepalive", "inputMessages", "outputMessages", "afi"] as const) assert.equal(missing[field], null)
|
||||
assert.equal(parseBgpSessions(server, [raw])[0].prefixesRx, 42)
|
||||
const selectedMissing = parseBgpSessions(server, [raw])[0]
|
||||
for (const field of ["prefixesRx", "prefixesTx", "holdTime", "keepalive", "inputMessages", "outputMessages", "localAs", "remoteAs"] as const) assert.equal(selectedMissing[field], null)
|
||||
assert.equal(selectedMissing.type, "Unknown")
|
||||
for (const s of [{}, { uptime: "1m" }, { established: "false" }, { state: "" }, { state: " " }, { state: "ActiveFuture" }, { state: "new-native-state" }]) {
|
||||
assert.equal(parseBgpSessions(server, [s])[0].state, "Unknown")
|
||||
assert.equal(parseBgpCatalogSessions(server, [s])[0].state, "Unknown")
|
||||
@@ -25,7 +27,14 @@ const invalid = parseBgpCatalogSessions(server, [{ ".id": "*3", "prefix-count":
|
||||
assert.equal(invalid.prefixesRx, null)
|
||||
assert.equal(invalid.holdTime, null)
|
||||
assert.equal(invalid.inputMessages, null)
|
||||
console.log("BGP parser: unknown/observed zero/timers/AFI, no UPDATE-prefix substitution, legacy preserved")
|
||||
for (const parse of [parseBgpSessions, parseBgpCatalogSessions]) {
|
||||
const row = parse(server, [{ "prefix-count": "0", "remote.messages": "0", "local.messages": "2", "hold-time": "0", "keepalive-time": "1s500ms", "remote.as": "4200000162", "local.as": "4200000163" }])[0]
|
||||
assert.equal(row.prefixesRx, 0); assert.equal(row.inputMessages, 0); assert.equal(row.outputMessages, 2)
|
||||
assert.equal(row.holdTime, 0); assert.equal(row.keepalive, 1.5); assert.equal(row.remoteAs, 4200000162)
|
||||
for (const invalid of ["-1", "12bad", "9007199254740992"]) assert.equal(parse(server, [{ "prefix-count": invalid, "remote.messages": invalid }])[0].prefixesRx, null)
|
||||
assert.equal(parse(server, [{ "hold-time": "9".repeat(320) + "s" }])[0].holdTime, null)
|
||||
}
|
||||
console.log("BGP parser: selected/catalog strict nullable AS/counters/timers/AFI, explicit zero and milliseconds, no UPDATE-prefix/default substitution")
|
||||
|
||||
assert.equal(missing.remoteAs, null)
|
||||
assert.equal(missing.localAs, null)
|
||||
|
||||
@@ -26,6 +26,9 @@ function parseDuration(s: string | undefined): number {
|
||||
case "s":
|
||||
total += n
|
||||
break
|
||||
case "ms":
|
||||
total += n / 1000
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -79,9 +82,12 @@ function detectState(s: RosBgpSession): string {
|
||||
/** Парсинг BGP-сессий с роутера — общая логика для HTTP-маршрута и alert-engine. */
|
||||
export function parseBgpSessions(server: ServerRow, raw: RosBgpSession[]): BgpSessionRead[] {
|
||||
return raw.map((s, idx) => {
|
||||
const remoteAs = parseInt(s["remote.as"] ?? "0") || 0
|
||||
const localAs = parseInt(s["local.as"] ?? "0") || 0
|
||||
const type: "eBGP" | "iBGP" = localAs > 0 && localAs === remoteAs ? "iBGP" : "eBGP"
|
||||
const asn = (value: string | undefined) => {
|
||||
const n = readCounter(value)
|
||||
return n !== null && n > 0 && n <= 4294967295 ? n : null
|
||||
}
|
||||
const remoteAs = asn(s["remote.as"]), localAs = asn(s["local.as"])
|
||||
const type = remoteAs === null || localAs === null ? "Unknown" : localAs === remoteAs ? "iBGP" : "eBGP"
|
||||
|
||||
const localCaps = parseCapabilities(s["local.capabilities"])
|
||||
const remoteCaps = parseCapabilities(s["remote.capabilities"])
|
||||
@@ -94,13 +100,12 @@ export function parseBgpSessions(server: ServerRow, raw: RosBgpSession[]): BgpSe
|
||||
if (s["extended-message-capability"] === "true") legacyCaps.push("Extended Messages")
|
||||
const caps = [...new Set([...localCaps, ...remoteCaps, ...legacyCaps])]
|
||||
|
||||
const holdTime = parseDuration(s["hold-time"]) || parseInt(s["active-holdtime"] ?? "0") || 90
|
||||
|
||||
const keepalive = parseDuration(s["keepalive-time"]) || 30
|
||||
const holdTime = readTimer(s["hold-time"]) ?? readCounter(s["active-holdtime"])
|
||||
const keepalive = readTimer(s["keepalive-time"])
|
||||
|
||||
const inputMessages =
|
||||
parseInt(s["remote.messages"] ?? s["total-messages-received"] ?? "0") || 0
|
||||
const outputMessages = parseInt(s["local.messages"] ?? s["total-messages-sent"] ?? "0") || 0
|
||||
readCounter(s["remote.messages"] ?? s["total-messages-received"])
|
||||
const outputMessages = readCounter(s["local.messages"] ?? s["total-messages-sent"])
|
||||
|
||||
const peerIp = (s["remote.address"] ?? "").replace(/\/\d+$/, "")
|
||||
|
||||
@@ -121,8 +126,8 @@ export function parseBgpSessions(server: ServerRow, raw: RosBgpSession[]): BgpSe
|
||||
uptime: s["uptime"] || null,
|
||||
holdTime,
|
||||
keepalive,
|
||||
prefixesRx: parseInt(s["prefix-count"] ?? s["total-updates-received"] ?? "0") || 0,
|
||||
prefixesTx: parseInt(s["total-updates-sent"] ?? "0") || 0,
|
||||
prefixesRx: readCounter(s["prefix-count"]),
|
||||
prefixesTx: null,
|
||||
inputMessages,
|
||||
outputMessages,
|
||||
capabilities: caps,
|
||||
@@ -132,11 +137,7 @@ export function parseBgpSessions(server: ServerRow, raw: RosBgpSession[]): BgpSe
|
||||
}
|
||||
|
||||
/** Каталог не заменяет отсутствующие показатели значениями по умолчанию старого API. */
|
||||
export type BgpCatalogSessionRead = Omit<BgpSessionRead, "holdTime" | "keepalive" | "prefixesRx" | "prefixesTx" | "inputMessages" | "outputMessages" | "remoteAs" | "localAs" | "type"> & {
|
||||
holdTime: number | null; keepalive: number | null; prefixesRx: number | null; prefixesTx: number | null;
|
||||
inputMessages: number | null; outputMessages: number | null; afi: string | null;
|
||||
remoteAs: number | null; localAs: number | null; type: "eBGP" | "iBGP" | "Unknown";
|
||||
}
|
||||
export type BgpCatalogSessionRead = BgpSessionRead & { afi: string | null }
|
||||
function readCounter(value: string | undefined): number | null {
|
||||
if (value === undefined || !/^\d+$/.test(value.trim())) return null
|
||||
const parsed = Number(value)
|
||||
@@ -145,21 +146,13 @@ function readCounter(value: string | undefined): number | null {
|
||||
function readTimer(value: string | undefined): number | null {
|
||||
if (value === "0" || value === "infinity") return 0
|
||||
if (!value || !/^(?:\d+(?:w|d|h|ms|m|s))+$/.test(value)) return null
|
||||
return parseDuration(value)
|
||||
const seconds = parseDuration(value)
|
||||
return Number.isFinite(seconds) && seconds >= 0 ? seconds : null
|
||||
}
|
||||
export function parseBgpCatalogSessions(server: ServerRow, raw: RosBgpSession[]): BgpCatalogSessionRead[] {
|
||||
return parseBgpSessions(server, raw).map((session, index) => {
|
||||
const s = raw[index]
|
||||
const asn = (value: string | undefined) => { const n = readCounter(value); return n !== null && n > 0 && n <= 4294967295 ? n : null }
|
||||
const remoteAs = asn(s["remote.as"]), localAs = asn(s["local.as"])
|
||||
return { ...session,
|
||||
remoteAs, localAs, type: remoteAs === null || localAs === null ? "Unknown" : remoteAs === localAs ? "iBGP" : "eBGP",
|
||||
state: s.established === "true" ? "Established" : s.state?.trim() ? detectState(s) : "Unknown",
|
||||
holdTime: readTimer(s["hold-time"]) ?? readCounter(s["active-holdtime"]),
|
||||
keepalive: readTimer(s["keepalive-time"]),
|
||||
prefixesRx: readCounter(s["prefix-count"]), prefixesTx: null,
|
||||
inputMessages: readCounter(s["remote.messages"] ?? s["total-messages-received"]),
|
||||
outputMessages: readCounter(s["local.messages"] ?? s["total-messages-sent"]),
|
||||
afi: s["remote.afi"]?.trim() || null,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -163,19 +163,19 @@ export interface BgpSessionRead {
|
||||
serverCountry: string
|
||||
name: string
|
||||
peerIp: string
|
||||
remoteAs: number
|
||||
localAs: number
|
||||
remoteAs: number | null
|
||||
localAs: number | null
|
||||
localId: string
|
||||
remoteId: string
|
||||
state: string
|
||||
type: "eBGP" | "iBGP"
|
||||
type: "eBGP" | "iBGP" | "Unknown"
|
||||
uptime: string | null
|
||||
holdTime: number
|
||||
keepalive: number
|
||||
prefixesRx: number
|
||||
prefixesTx: number
|
||||
inputMessages: number
|
||||
outputMessages: number
|
||||
holdTime: number | null
|
||||
keepalive: number | null
|
||||
prefixesRx: number | null
|
||||
prefixesTx: number | null
|
||||
inputMessages: number | null
|
||||
outputMessages: number | null
|
||||
capabilities: string[]
|
||||
lastError: string | null
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user