Skip to content

FreeSBC v0.6.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 03:48
· 14 commits to main since this release
8af1a6a

FreeSBC v0.6.0 cuts about 30% of the allocations per call on the signaling path, raises the UDP SIP receive buffer request to 8 MiB, adds per-socket UDP drop metrics, and counts reads from banned sources. It is built with Go 1.27.3 for GO-2026-6809. Configuration is unchanged: a v0.5.1 file loads as is.

curl -fsSL https://github.com/rasonyang/freesbc/releases/latest/download/install.sh | sh

Breaking changes

None. No configuration key, CLI command, admin API field, metric name or label changed. Two things look different after the upgrade:

  • freesbc_shield_drops_total{reason="banned"} now rises during a ban (#250, closes #249). Before, reads from a banned source were dropped before parsing and not counted, so the series stayed nearly flat while a ban was in force. It now counts one per dropped UDP datagram or WS/WSS frame (on tcp/tls, usually one chunk before the connection closes). Expect much higher values from scanners that keep sending, and adjust alerts that assumed a low rate. freesbc_edge_stream_refused_total{reason="banned"} is unchanged.
  • A host with net.core.rmem_max below 8 MiB now logs a startup WARN (udp socket receive buffer below request), once per UDP SIP socket, and keeps the smaller buffer. This includes hosts set to the 4 MiB that earlier docs asked for. Raise rmem_max to 8388608 to clear it (see "UDP buffer" below).

Performance

  • Fewer allocations per call (#247, closes #173). A new benchmark runs a whole client call (INVITE, 180, 200, ACK, BYE, 200) through a real edge over loopback.
    • BenchmarkEdgeCall: 1125 to 777 allocations per call (-31%), 66.3 KB to 58.9 KB (-11%).
    • BenchmarkEdgeCallParallel on Linux, 8 vCPU: about 12.2k to 15.8k calls/s, CPU per call 464 to 389 µs, GC CPU per call down about a fifth, stack growth (runtime.newstack) 8.2% to 4.6% of CPU.
    • How: case-insensitive header matching without lower-casing every header, the read filter reads addresses without a string round trip, cached topology hosts, one stored 2xx instead of a second clone, each handler goroutine's stack grown once while shallow, and sdp.Build/Negotiate rewritten without maps (Build output is byte-identical to the previous marshaller, checked over randomized inputs and the fuzz targets). Forwarding an RTP packet no longer allocates.
    • Trust and latching behave as before. The rest of the allocations and stack growth are inside sipgo.
  • UDP buffer: the SIP receive request goes from 4 MiB to 8 MiB (#248, closes #235). It applies to the public edge.listen.udp socket and the private private.ip:5060 socket. The kernel grants it in full only with net.core.rmem_max of at least 8 MiB (Linux then allocates 16 MiB). This is a stopgap: it rides out longer waits but does not remove them, and it is not yet measured on the three hosts.
  • Why carrier-in drops above 3500 CPS (#235). A local re-run on 4 CPUs found that both UDP SIP sockets drop, the private one slightly more. GC mark phases (0.5 to 1.6 s each) hold most of the CPUs, and each socket's single read loop waits behind them, up to 164 ms without a read. Average CPU had headroom. GOGC=200 delays the onset but costs 7.8 GB RSS. The real fix is less GC work (#170 in v0.5.1, #173 in this release). 3500 CPS stays the loss-free carrier-in figure on 4 vCPU until the next three-host run.

Metrics

  • freesbc_udp_socket_drops_total{socket="public|private"} (counter) and freesbc_udp_socket_rx_queue_bytes{socket} (gauge) (#248). They name which UDP SIP socket the kernel dropped datagrams on, and how full its receive queue is at the scrape. They come from /proc/self/net/udp and udp6 at scrape time, Linux only. A socket that is not bound (no edge.listen.udp) has no series. The namespace-wide freesbc_udp_receive_buffer_errors_total and freesbc_udp_in_errors_total are unchanged.
  • freesbc_shield_drops_total{reason="banned"} counts reads the read filter drops from banned sources (#250); see Breaking changes.

Build

  • Go 1.27.3 (in #250). govulncheck flagged GO-2026-6809 in Go 1.27.2's crypto/x509, reachable from TLS reads on stream connections. Release binaries are built with 1.27.3; building from source now needs Go 1.27.3 or later.

Docs

  • README (#251, #252, closes #240, #241, #242). It now leads with what FreeSBC is, a WebUI screenshot (light and dark), install, and five headline performance numbers. The Features, Status & limitations and Layout sections are gone; their details moved to docs/.
  • docs/edge.md gains a "Scope rule" section (the two questions a feature must pass), and SDES-SRTP is listed under Known limitations.
  • docs/config.md gains an admin Endpoints table (every route, its purpose and auth), the tls_cert_* health conditions, and the Config tab's read-only view, Validate and line diff.
  • docs/performance.md adds the full-call benchmark, updated micro-benchmarks and the #235 analysis. docs/edge.md, docs/install.md and docs/troubleshooting.md now say 8 MiB for rmem_max.

Test rig and CI

  • The perf kit records per-socket kernel drops and receive-queue peaks for each step (udp_pub_drops, udp_priv_drops, udp_*_rxq_peak_bytes in steps.csv) (#248).
  • PROFILE_AT=<rate> saves a CPU profile, an execution trace, a goroutine dump and a heap profile at that step (#248).
  • The rig images build on the Go version in go.mod, and a CI step fails when a golang:<version> tag in the repo differs from it (#256, closes #253).

Known limitations and follow-ups

  • #257: the next monthly three-host run re-measures the carrier-in ceiling with the 8 MiB buffer, and the GC cuts of #170 and #173. Until then 3500 CPS is the loss-free carrier-in figure on 4 vCPU.
  • #254: the WebUI header shows vv0.6.0 on release builds.
  • #255: some WebUI buttons and the theme icon keep the old colours when the colour scheme changes.
  • #246: no release signing yet. SHA256SUMS guards against corruption only.