summaryrefslogtreecommitdiff
path: root/src
Commit message (Collapse)AuthorAgeFilesLines
* lib: Allow up to two TLPs per recovery episodeDimitri Staessens37 hours1-8/+22
| | | | | | | | | | | RFC 8985 §7.3 permits up to two tail loss probes before falling back to RTO. Previously FRCP allowed exactly one TLP per episode, making tail-loss recovery dependent on a successful first probe; if that probe was lost the sender fell straight to slow RTO with exponential backoff. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Further align FRCP with TCP RFCsDimitri Staessens37 hours1-43/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Only the HoL slot retransmits on RTO; non-HoL slots defer and rely on SACK/RACK fast-rxm for recovery. Matches RFC 6298 §5.4 + RFC 8985 §3 and Linux tcp_retransmit_skb(head, 1). Eliminates the spurious-RTO storm where ~50-66% of retransmits arrived as duplicates at the peer. Co-fixes for three latent state-machine bugs that the previous spurious-retx mask was hiding: - recovery_enter: seal recovery_high at the false→true edge only (RFC 6582 §3.2). Previously extended on every gap-SACK, which trapped the sender in NewReno indefinitely once any cum-ACK fell behind the moving recovery_high. - rtt_sample_eligible: drop the in_recovery super-gate. Karn at the per-slot SND_RTX|SND_TLP level is already correct (matches Linux). - rxm_due defer interval: use base RTO, not rto<<rto_mul. Inheriting HoL's backoff parked deferred slots tens of seconds in the future. Bring RACK reorder-window scaling into RFC 8985 §7.2 compliance: reo_wnd_mult widens at most once per RTT, gated via a srtt-elapsed check in reo_wnd_on_dsack. Stat refactor for clearer attribution: rename rxm_snd → rxm_rto (now RTO-driven sends only), add rxm_nack and rxm_due_defer, split rxm_rcv into total FRCT_RXM arrivals and rxm_dup_rcv (duplicates). Expose rx/tx ring queue depths as RIB stats. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Set a timeout on FRCT control packetsDimitri Staessens37 hours2-17/+130
| | | | | | | | | | | | | Time out frct_tx for control packets at 250us so a full tx ring cannot stall the timer wheel (and with it KA, TLP, RXM fires). DATA frames (fresh, RXM, TLP, FIN) keep blocking - dropping them would lose recovery progress. Add inact_drop, drf_rebase, rq_released, tlp_snd, sdu_snd_alloc, sdu_snd_tx, sdu_sole, rxm_tx_dead, and per-type tx_drop counters. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add tail loss probe (TLP) to FRCPDimitri Staessens37 hours1-21/+162
| | | | | | | | | | | | | | | | | | | | | | | | The previous bugfixes that fixed a false-positive inactivity timer check unmasked the need for the tail loss probe (TLP) to quickly recover from loss of the HoL. When the sender finishes its app data with packets still inflight, RACK fast-rxm cannot fire (no ACK arrives), pre-DRF NACK is gated on rcv_cr.inact, and rto_mul climbs into seconds before the next RXM fire — recv-side deadline expires first. This adds the RFC 8985 §7.2 TLP: PTO = 2*SRTT + max_ack_delay (t_a), capped by the HoL slot's current RTO deadline. Probe fires from frcti_snd and after frcti_ack_rcv; per §7.3 at most one TLP per recovery episode, tracked via tlp_high_seq. On fire, re-emit HoL via fast_rxm_send and hand off to RTO — no PTO self re-arm. A new SND_TLP slot flag is Karn-skipped for RTT sampling, cleared by RTO retransmit or NACK-driven fast-rxm, and clears rto_mul on its TLP-ACK (rto_mul carries no CC meaning in FRCP). Also caps MAX_RTO_MUL at 8 instead of 20. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix underrun in activity timerDimitri Staessens37 hours1-22/+50
| | | | | | | | | | | The inactivity timers are updated under rdlock with atomics on the time stamp. Inactivity is measured by comparison between the act stamp against the thread's own current time (now_ns). A different thread could already have updated the act stamp, causing undderun in the signed comparison and causing a false-positive on the inactive test. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Skip DRF rebase on same-epoch retransmitDimitri Staessens4 days1-2/+24
| | | | | | | | | | | | | | | | | | | | On some stalls the receiver can go inactive and NACK-driven HoL retransmits and brief snd-window drains can deliver a DRF-flagged packet that's still part of the current receive epoch (rxm_pkt_prepare preserves the original flags). This treats in-window DRF and RXM-flagged DRF arrivals as same-epoch once the window is seeded and skip the release_rq + lwe/rwe rebase that would otherwise wipe valid OOO fragments from rq[]. Bootstrap (lwe == rwe) still rebases unconditionally so a NACK-driven retransmit of a lost initial DRF can seed the receiver. Harden seqno_rotate to redraw the ISN until it falls outside the peer's current rcv window, closing the ~RQ_SIZE / 2^32 collision where a true new epoch would be misclassified as same-epoch. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Free secure memory on process exitDimitri Staessens4 days2-4/+9
| | | | | | | | | | | There was a missing crypt_secure_malloc_fini() in the process init/fini path. Also fixes a 0 return from OpenSSL RAND_bytes() being interpreted as succes instead of failure. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Update FRCP implementationDimitri Staessens4 days20-1401/+4704
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The Flow and Retransmission Control Protocol (FRCP) runs end-to-end between two peers over a flow. It provides reliability, in-order delivery, flow control, and liveness. Note that congestion avoidance is orthogonal to FRCP and handled in the IPCP. A fixed 16-octet header, network byte order, is prefixed to every FRCP packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | flags | hcs | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | window | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | seqno | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ackno | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | payload (variable) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ hcs is a CRC-16-CCITT-FALSE checksum over the PCI (and the stream extension when present), verified before any flag-driven dispatch. A single packet can simultaneously carry DATA + ACK + FC + RXM by OR-ing flag bits. An optional CRC trailer covers the body on DATA when qs.ber == 0, and on every SACK packet; an optional AEAD wrap (per-flow keys) sits outermost. Flag bits (MSB-first; bits 13..15 reserved, MUST be zero): +------+--------+--------+----------------------------------------+ | Bit | Mask | Name | Meaning | +------+--------+--------+----------------------------------------+ | 0 | 0x8000 | DATA | Carries caller payload | | 1 | 0x4000 | DRF | Start of a fresh data run | | 2 | 0x2000 | ACK | ackno field valid | | 3 | 0x1000 | NACK | Pre-DRF nudge (seqno informational) | | 4 | 0x0800 | FC | window field valid (rwe advertisement) | | 5 | 0x0400 | RDVS | Rendezvous probe (window-closed) | | 6 | 0x0200 | FFGM | First Fragment of a multi-fragment SDU | | 7 | 0x0100 | LFGM | Last Fragment of a multi-fragment SDU | | 8 | 0x0080 | RXM | Retransmission | | 9 | 0x0040 | SACK | Block list follows in payload | | 10 | 0x0020 | RTTP | RTT probe / echo (payload follows) | | 11 | 0x0010 | KA | Keepalive | | 12 | 0x0008 | FIN | End of stream marker | | 13-15| -- | -- | Reserved (MUST be zero) | +------+--------+--------+----------------------------------------+ (FFGM, LFGM) encodes the fragment role of a DATA packet (SCTP-style B/E): 11=SOLE, 10=FIRST, 00=MID, 01=LAST. Each fragment carries its own seqno; Retransmission recovers fragments individually, reassembly runs at consume time. In stream mode FFGM/LFGM are unused; per-byte position is carried by the stream extension below and end-of-stream is signalled by FIN on a 0-byte DATA packet. SACK payload (FRCT_ACK | FRCT_FC | FRCT_SACK): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | n_blocks | padding (2 octets) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | start[0] | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | end[0] | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... n_blocks pairs total ... Each block describes a *present* (received) range strictly above the cumulative ACK in the PCI ackno. D-SACK (RFC 2883) is signalled in-band as block[0] - no flag bit, no extra framing - and consumed by the RACK reo_wnd_mult scaler (RFC 8985 sec. 7.2). RTTP payload (FRCT_RTTP only; 24 octets): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | probe_id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | echo_id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + nonce (16 octets, echoed verbatim) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Stream PCI extension (in_order == STREAM only; 8 octets after the base PCI on every DATA packet): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | start | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | end | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ start, end are monotonic 32-bit byte offsets; end - start equals the on-wire payload length. Stream mode is negotiated at flow allocation; the extension is present iff stream mode is in use, never on a per-packet basis. Service modes are an orthogonal (in_order, loss, ber) vector selected at flow_alloc; the cubes above map to the axes: +----------------+---------+------+-----+-----------------------+ | Cube | in_order| loss | ber | Engaged | +----------------+---------+------+-----+-----------------------+ | qos_raw | 0 | 1 | 1 | Raw passthrough | | qos_raw_safe | 0 | 1 | 0 | Raw + CRC trailer | | qos_rt | 1 | 1 | 1 | FRCP, no FRTX, no CRC | | qos_rt_safe | 1 | 1 | 0 | FRCP, no FRTX, CRC | | qos_msg | 1 | 0 | 0 | FRCP + FRTX | | qos_stream | 2 | 0 | 0 | FRCP + FRTX, stream | +----------------+---------+------+-----+-----------------------+ in_order=0 sends raw datagrams with no PCI (UDP-equivalent); in_order=1 engages FRCP with SDU framing; in_order=2 (stream) requires loss=0 and is rejected otherwise. loss=0 engages the FRTX retransmit machinery. ber=0 appends the CRC-32 trailer; QOS_DISABLE_CRC at build time forces ber=1 for development. Encryption is a separate per-flow attribute layered as an AEAD wrap outside the FRCP packet. Heritage: delta-t (Watson 1981) supplies timer-based connection management - no SYN/FIN handshake, the DRF marker, the t_mpl / t_a / t_r timers. RINA (Day 2008) supplies the unified flow_alloc(name, qos, ...) primitive and the orthogonal QoS-cube axes. Loss detection follows TCP/QUIC practice (RFCs 2018, 2883, 6582, 6298, 8985); RTT probing is nonce-authenticated like QUIC PATH_CHALLENGE. Adds oftp, a minimal file-transfer tool over an FRCP stream flow. The client reads from stdin or --in FILE and writes through a flow_alloc(qos_stream); the server (--listen) calls flow_accept and writes to stdout or --out FILE. Both sides compute a CRC-64/NVMe over the bytes they handle and print the result. The server rejects flows whose negotiated qs.in_order != STREAM. Two FRCP knobs are exposed via env vars on either side: OFTP_FRCT_RTO_MIN fccntl FRCTSRTOMIN (ns) OFTP_FRCT_STREAM_RING_SZ fccntl FRCTSRRINGSZ (octets) The ocbr_client gains an OCBR_QOS env var to pick the cube the client uses for flow_alloc; recognised values are raw, safe, rt, rt_safe, msg, stream. Unknown values fall back to raw with a warning on stderr. Without the env set behaviour is unchanged. Removes the deprecated lib/timerwheel.c Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Use push/pop for ssm_pk_buff opsDimitri Staessens4 days7-29/+29
| | | | | | | | | Renames the allocation for head/tail to push/pop instead of alloc/release as it's simpler and shorter. Took this approach insted of adopting the kernel's push/pull/put/trim. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* build: Remove deprecated cmake optionsDimitri Staessens4 days2-2/+0
| | | | | | | RXM_BUFFER_ON_HEAP and SSM_POOL_BLOCKS were no longer used. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd-eth: Tune raw sockets and retry queriesDimitri Staessens4 days2-62/+113
| | | | | | | | | | | | | | | | | | | Add IPCP_ETH_SNDBUF/RCVBUF cmake build options so deployments can size the AF_PACKET socket buffers without patching code. Drop the O_NONBLOCK fcntl on the raw socket in favour of per-recvfrom MSG_DONTWAIT so race-loser reader threads exit with EAGAIN without spamming the log. Track frame send failures and the SO_SNDBUF size in the eth/summary RIB; log a one-shot warning when the kernel reports AF_PACKET drops. Retry name queries up to NAME_QUERY_RETRIES times within NAME_QUERY_TIMEO; a single lost ARP-style mgmt frame no longer fails the query. Bump IRMd QUERY_TIMEOUT from 200 ms to 2200 ms so the IRMd budget exceeds the new shim retry window. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Use const for ssm_pk_buff gettersDimitri Staessens4 days1-6/+6
| | | | | | | | | Mark ssm_pk_buff_get_off, _head, _tail, and _len as taking a const struct ssm_pk_buff *. Cast through the flex array in _head and _tail since the buffer view they return remains mutable. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* tools: Add timeout option to opingDimitri Staessens4 days2-2/+14
| | | | | | | | | Add a -W/--timeout option to override the per-packet recv timeout. The default is 2000 ms. Raises the receive buffer to 16 KiB so larger SDUs aren't truncated (useful for fragmentation tests later on). Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Pass MTU from IPCP to process for FRCTDimitri Staessens4 days15-13/+123
| | | | | | | | | FRCT needs to know the MTU for fragmentation. The MTU is now passed from the layer serving the flow to the process as part of flow allocation. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* tools: Fix server mutex init in opingDimitri Staessens4 days1-3/+13
| | | | | | | | The pthread_mutex_init and pthread_mutex_destroy were missing, resulting in undefined behaviour. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add generic hierarchical timing wheelDimitri Staessens4 days4-0/+972
| | | | | | | | | Introduce a generic 3-level / 256-slot deadline-ordered callback queue (1 ms / 16 ms / 256 ms per-slot resolution at levels 0/1/2). Will replace the existing timerwheel.c. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Rename PROG_* config to PROC_*Dimitri Staessens4 days9-48/+48
| | | | | | | | | Per-process flow / fd / fqueue limits are properties of a process, not a program; align the naming. Mechanical rename of PROG_MAX_FLOWS, PROG_RES_FDS, and PROG_MAX_FQUEUES to PROC_*. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Reject outbound packets on ethDimitri Staessens4 days1-2/+16
| | | | | | | | | | | | | AF_PACKET under `tc netem duplicate`, produces an extra PACKET_OUTGOING frame at the source that receive path didn't reject. Read with recvfrom(2) and discard frames whose sll_pkttype is PACKET_OUTGOING. Restores the dst-MAC check body (defense in depth, also bumps n_bad_id) so any frame addressed neither to us nor the broadcast MAC is dropped before flow lookup. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Use tpm.h for TPM testDimitri Staessens4 days1-1/+1
| | | | | | | | The threadpool manager (TPM) test unnecessarily included the source instead of the header. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd, lib: Minor cleanup in oap/srv and irm.protoDimitri Staessens4 days2-8/+4
| | | | | Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* include: Centralise atomic helpers in atomics.hDimitri Staessens4 days2-25/+5
| | | | | | | | Moves the atomics macros that were defined between eth and ssm_pool to their own header. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Drop replayed flow alloc requestsDimitri Staessens4 days6-6/+112
| | | | | | | | | | | | | | A duplicating link could deliver the same alloc request twice. OAP detected the replay but still replied over the wire, so the requester saw a second flow_alloc_reply on an already-allocated flow and reg_respond_alloc tripped its PENDING-state assertion. Add EREPLAY so the OAP server can signal replays distinctly; flow_accept drops them silently. As a safety net, reg_respond_alloc warn-drops late replies instead of asserting. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Expose ipcpd-eth flow statistics via RIBDimitri Staessens4 days2-8/+333
| | | | | | | | | | | | | Adds an IPCP_ETH_FLOW_STATS cmake option (gated on HAVE_FUSE; default off) exposing per-flow and aggregate frame counters at /<ipcp>/eth/{summary,<fd>}. Counters use RELAXED atomics; the macros expand to ((void) 0) when the option is off. Per-flow and global counters live in nested stat structs. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix pool_sharding_testDimitri Staessens4 days3-71/+39
| | | | | | | | The test was not correctly taking the correct size class. Moved the select_size_class to the common header so tests can use it. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* tools: Use distinct exit codesDimitri Staessens4 days6-40/+47
| | | | | | | | | | | | | | | The tools will now use the following convention: 0 — success 1 — runtime/I/O failure or packet loss 2 — setup failure oping now uses a SIGALRM to exit on duration tests. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Drain rbuff before closeDimitri Staessens4 days1-4/+48
| | | | | | | | | | | | | | | | | ssm_rbuff_close used to unmap the SHM page immediately, leaving any in-flight peer-process thread that was inside pthread_mutex_lock or pthread_cond_wait on the SHM-resident sync primitives reading freed memory. Adds an n_users counter, bumped on entry and dropped on exit of every function that touches the mutex / cond vars (write, write_b, read, read_b, fini), and have ssm_rbuff_close poll-spin until the counter drains before tearing down. ssm_rbuff_read now re-checks IS_EMPTY after taking the mutex, plugging a TOCTOU where two readers could both pass a lock-free fast path and the loser would read a stale TAIL. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Drop RIB lock before component callbackDimitri Staessens4 days1-6/+12
| | | | | | | | The RIB lock only needs to protect operations on the components list. This avoids holding the lock on longer RIB reads. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Validate wire frame lengthsDimitri Staessens4 days2-6/+10
| | | | | | | | Asserting frame lengths coming from the wire was a severe flaw. Fixed by gracefully dropping runt frames. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Rename ssm_pk_buff_get_idx to ssm_pk_buff_get_offDimitri Staessens2026-05-066-43/+44
| | | | | | | | | | The shared memory pool is now offset based instead of block index-based like the old shm_rdrbuff allocator. This renames the API more consistently. Also changes variables names to off instead of idx for consistency. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix pool_copy_spb and np1_flow_writeDimitri Staessens2026-05-061-15/+19
| | | | | | | | The pool_copy_spb function was consuming the packet buffer on error, causing double free errors. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix and clean up crc implementationDimitri Staessens2026-05-063-49/+38
| | | | | | | | | Fixes detection of PMULL on aarch64 without crypto extensions. Adds a crc64_nvme_step helper function in CRC64 to avoid code duplication and cleans up the comments. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Move CRC implementations to a subfolderDimitri Staessens2026-05-0611-8/+26
| | | | | Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Add header checksum to ipcpd-ethDimitri Staessens2026-05-061-6/+56
| | | | | | | | | The internal flow allocator header had no checksum protection. While it is protected by the Ethernet FCS, lacking a header checksum fails netem corruption tests. It adds protection against in-memory bitflips. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add CRC-8 and CRC-16 checksumsDimitri Staessens2026-05-068-0/+358
| | | | | | | These checksum will be handy for header checksums. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add CRC-64/NVMe checksumDimitri Staessens2026-05-066-0/+545
| | | | | | | | | | | | | | | | | Add CRC-64/NVMe implementation with compile-time hardware backend selection: x86 PCLMUL+SSE4.1 fold-by-16 (HAVE_PCLMUL) aarch64 PMULL fold-by-16 when (HAVE_PMULL) and a byte-table fallback. It's added as HASH_CRC64 to enum hash_algo (in the internal-use-only section after HASH_MD5). Both mem_hash() and hash_len() early-return for HASH_CRC64 because libgcrypt has no CRC-64/NVMe. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* cmake: Add CPU feature detection helperDimitri Staessens2026-05-061-0/+2
| | | | | | | | | | | | Add cmake/utils/CPUUtils.cmake providing detect_cpu_feature() plus detect_pclmul() and detect_pmull() that compile-test for x86 PCLMULQDQ+SSE4.1 and aarch64 FEAT_PMULL respectively. This will be useful for hardware accelerated CRC64/NVMe integrity checks. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Remove dead codeDimitri Staessens2026-03-141-130/+0
| | | | | | | | The oap.c source code was split into separate modules in the oap/ folder but some of it was never correctly removed. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix certificate DER encoding and key buffersDimitri Staessens2026-03-147-41/+41
| | | | | | | | | | | i2d_X509() allocated buf->data via OPENSSL_malloc(), but callers free it with freebuf() which uses free(). Fix by allocating with malloc() and encoding directly into the buffer. Also replaces MSGBUFSZ with CRYPT_KEY_BUFSZ (4096) for key material buffers and removes leftover debug logging. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix initialization when listing namesDimitri Staessens2026-03-142-2/+2
| | | | | | | | Now uses calloc to zero the previously uninitialized security path fields. Also fixes a check in protobuf.c Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Relax test flow accept timeoutDimitri Staessens2026-03-141-1/+1
| | | | | | | | The reg_test still had false-positive failures on slow machines / woodpecker. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix rejected flow allocation on localDimitri Staessens2026-03-141-9/+6
| | | | | | | | | When the server rejects the flow, the local didn't send the flow_alloc response back to the IRMd, causing the irmd and client to time out instead of being notified of the failed allocation immediately. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix missing cleanup in authentication pathDimitri Staessens2026-03-147-2/+19
| | | | | | | | | | | | | When auth_verify_crt fails (e.g., missing root CA), crypt_get_pubkey_crt has already allocated pk but only crt was freed. Adds a crypt_cleanup() function to wrap OpenSSL_cleanup(), as OpenSSL lazily initializes a global decoder/provider registry the first time PEM_read_bio or OSSL_DECODER_CTX_new_for_pkey is called, and this leaves some memory owned by OpenSSL that triggers the leak sanitizer. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Add tests for missing root CADimitri Staessens2026-03-142-0/+125
| | | | | | | | | This adds authentication tests to verify flows are rejected with a missing root CA certificate in the store. Also adds one for the OAP protocol. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix chown of GSPP to ouroboros groupDimitri Staessens2026-03-141-1/+3
| | | | | | | | The Global Shared Packet Pool (GSPP) was not correctly chowned to the ouroboros group. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* irmd: Fix bad merge in reg.cHEAD0.23.0masterSander Vrijders2026-02-221-4/+0
| | | | | | | A merge conflict was left unresolved, resulting in compilation errors. Signed-off-by: Sander Vrijders <sander@ouroboros.rocks> Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
* irmd: Fix memleak in reg testsDimitri Staessens2026-02-222-0/+8
| | | | | | | | | | Call freebuf(pbuf) before returning from each test thread function. Since clrbuf zeroes pbuf.data to NULL on the success path, free(NULL) is safe. On the failure path of reg_respond_*, it now properly frees the still-allocated data. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Skip vertices with empty forwarding listsDimitri Staessens2026-02-221-21/+23
| | | | | | | | | | | | | | | Fixes ECMP routing table to skip unreachable vertices with empty forwarding lists, avoiding uninitialized nhop access. Replace inner vertex list walk with bounded index loop instead of using a list_for_each to track indices (which confuses the static analyzer as it seems it can't prove the index remains valid). Remove spurious free(*dist) on ECMP success path (caller frees). Extract edge cleanup into free_edges helper in del_vertex to avoid a static analyzer false positive. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix ssm pool double freeDimitri Staessens2026-02-222-2/+5
| | | | | | | | | | Remove double-free in ssm_pool_destroy — ssm_pool_close already frees the pool. The pool sharding test had a free spbs/ptrs on partial malloc failure. Now initializes children array to -1 to prevent reading uninitialized values. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* lib: Fix invalid malloc pointer typeDimitri Staessens2026-02-221-1/+1
| | | | | | | | | The static analyzer complained about the struct in6_addr malloc being converted to uint8_t *. Fixed by casting IN6_LEN to a size_t numeric value instead of the direct sizeof. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
* ipcpd: Fix unused values in unicast IPCPDimitri Staessens2026-02-222-4/+2
| | | | | | | | | | | Use the key in the store operation in the DHT, to avoid static analyzer seeing it as being set without being used in release builds. The length of the packet buffer is only used when tracking DT stats, so should be set within the IPCP_FLOW_STATS guard. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>