Skip to content

feat(libSceNet): keep TCP option state - #11272

Open
Queuse wants to merge 3 commits into
boykopovar:mainfrom
Queuse:codex/net-tcp-options
Open

Queuse wants to merge 3 commits into
boykopovar:mainfrom
Queuse:codex/net-tcp-options

Conversation

@Queuse

@Queuse Queuse commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What

Store and read back TCP_MAXSEG, TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT for libSceNet stream sockets, including bounded output, input validation, socket isolation and keepalive inheritance through accept.

MSS starts at 536 for IPv4 and 1220 for IPv6, requires a peer before a set and raises accepted values below 216 to 216. Defaults and validation follow the PS5 13.60 libkernel_sys probes pinet4 and pmaxseg, with FreeBSD rules for unmeasured cases. The pmaxseg evidence also underlies #11251, which changes libkernel rather than these libSceNet paths.

These options keep guest state; they do not configure host MSS or keepalive timers. Connected MSS initially reports the stored family default rather than the negotiated segment. Direct libSceNet measurements on PS5 remain unavailable; the library debt records these limits.

#9525/#9542 and #10502 are now merged. This refresh preserves #10502's socket names/diagnostics alongside all TCP state and accept inheritance. Overlap snapshot 4a6693acf8 reported a debt-only intersection with #9948; #11272-first remains proposed, awaiting confirmation. Five comparisons were incomplete at that snapshot (#5836, #9932, #11969, #12104, #12288). Their shared-file changes were inspected; this was not a combined runtime pass. #11969 has since closed in favor of the #12682 -> #12688 -> #12700 stack. Future transport/close coordination follows those successors; the original scan and runtime results below remain tied to their stated heads.

Tested

Windows 11 x86-64, WinLibs MinGW-w64 GCC 15.2.0-r7, Ninja, Release. Exact head 53d19a3d87 includes main dacca6bb88.

  • Rebuilt the affected libc/libkernel/libSceNet closure and eight fixtures. guest_net_tcp_options, guest_net_protocol, guest_net_nodelay_readback, guest_net_buffer_validation, guest_net_socket_state, guest_net_boolean_readback, guest_net_oob_inline and guest_sce_net: 8/8 pass, no skips.
  • The socket-record conflict is resolved by retaining the four TCP fields and the new name field. Getter paths, diagnostics, test registrations and both debt updates coexist.
  • Public-header audit: 368 libraries, 13,051 exports. Test-registration audit, conventions and whitespace checks pass.
  • Canonical overlap snapshot 4a6693acf8: one reported debt intersection and five incomplete comparisons, as recorded above. A trial merge with that consulted main is clean; the runtime results belong to the published head/base, not that later merged tree.
  • The firmware 13.42 disassembly/emulator report is third-party Net-to-kernel forwarding evidence. It is distinct from the cited firmware 13.60 console probes and from direct Net hardware measurement.
  • No fresh Linux/macOS runtime, full hosted product build, title or console run. TCP_KEEPINIT remains unsupported; the retail call-site report is not a claim that these changes unblock a title.

Hosted run 40667809045 passed the Windows job on 53d19a3d87, including configuration, registration and the host-only link step. Full product build/test steps and the Linux, relinker and specialized runtime jobs were skipped; this does not add a hosted guest TCP runtime or title run.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none; original feat(libSceNet): expose socket type and listen state #9525/feat(libSceNet): read reuse and broadcast flags #9542 merge order fulfilled
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the state model and the socket lifecycle paths for TCP_MAXSEG and the keepalive options, including family defaults, stream checks, unconnected/listening MSS rejection, the 176-to-216 clamp, input/output truncation, per-socket isolation, timer bounds, and accept-time inheritance. The zero-as-default readback for keepalive values matches FreeBSD's TP_KEEPIDLE/TP_KEEPINTVL/TP_KEEPCNT behavior. The focused test covers both libSceNet and libkernel entry points and verifies that option state does not leak between sockets or between existing and newly accepted connections.

On the exact head I ran git diff --check, tools/check_conventions.py --base upstream/main, and the public-header audit; all pass (368 libraries, 12,202 exports). The author reports seven focused Windows tests passing and a deliberate failure against the previous libSceNet binary for the unconnected-MSS case. Hosted policy checks pass, but product-build jobs are skipped, and the cited PS5 measurements cover libkernel_sys rather than direct libSceNet calls; that limitation is documented. I found no blocking issue.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 9932 docs/dev/debt/libSceNet.md L69-70
PR 9948 docs/dev/debt/libSceNet.md L69-70
PR 12683 docs/dev/debt/libSceNet.md L69-70
PR 12918 core/libs/prx/libSceNet/Export.cpp L1651

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5836 core/libs/prx/libSceNet/CMakeLists.txt
core/libs/prx/libSceNet/Export.cpp
core/libs/tests/GuestSceNet.cpp
docs/dev/debt/libSceNet.md
PR 12104 docs/dev/debt/libSceNet.md
PR 12682 core/libs/prx/libSceNet/Export.cpp
PR 12688 core/libs/prx/libSceNet/Export.cpp
PR 12700 core/libs/prx/libSceNet/Export.cpp
PR 12965 core/libs/prx/libSceNet/Export.cpp
PR 14212 docs/dev/debt/libSceNet.md

@oneandonlydean oneandonlydean self-assigned this Oct 26, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@BunnyFl

BunnyFl commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

On "direct PS5 libSceNet behavior is unmeasured": firmware 13.42's libSceNet.sprx (sha256 3d30fe383092f56a…) passes TCP options straight to libkernel. Per the disassembly, sceNetSetsockopt (0x4390) and sceNetGetsockopt (0x4400) check two things before calling libkernel's _setsockopt/_getsockopt with the caller's five arguments unchanged:

  • a SOL_SOCKET option with bit 23 set returns 0x8041012A;
  • if the library isn't initialized, the call returns 0x804101C8.

sceNetSetsockopt retries on EINTR. A _setsockopt failure comes back as 0x80410100 | errno, with the library's own errno set to the same number.

I ran both exports in an x86-64 emulator (unicorn), with the library's initialized flag set directly and _setsockopt/_getsockopt logged. Three runs gave identical output:

call not initialized initialized
Setsockopt(3, IPPROTO_TCP, 0x1 / 0x2 / 0x100 / 0x200 / 0x400, &v, 4) 0x804101C8 _setsockopt(3, 6, same name, &v, 4), 0
Setsockopt(3, SOL_SOCKET, 0x8, &v, 4) 0x804101C8 _setsockopt(3, 0xffff, 0x8, &v, 4), 0
Setsockopt(3, SOL_SOCKET, 0x800000, &v, 4) 0x8041012A 0x8041012A, no call
Getsockopt(3, IPPROTO_TCP, 0x200, &v, &len) 0x804101C8 _getsockopt(3, 6, 0x200, &v, &len), 0

When _setsockopt failed with errno 22, 42 or 54, sceNetSetsockopt returned 0x80410116, 0x8041012A and 0x80410136, and the library's errno held the same number. ENOTSOCK (38) is the exception: it came back as 0x80410109, with errno 9 (EBADF).

So for TCP_MAXSEG, TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT, a direct libSceNet call on 13.42 reaches the same libkernel call with the same values, so on that module the values and results the libkernel_sys probes measured apply to direct libSceNet calls too. Only the wrapping differs: the initialization check, the 0x80410100 | errno result, and ENOTSOCK reported as EBADF. That's for 13.42's module; the cited probes ran on 13.60.

@Queuse

Queuse commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

I resolved the conflict with main e2d457be34 and pushed 552191fe9c. The TCP state paths now coexist with the merged socket-state, boolean, OOBINLINE, protocol and NODELAY getters. All seven rebuilt focused Windows tests pass, with no skips; headers, registration, conventions and whitespace checks pass.

Thanks for the firmware 13.42 forwarding evidence. I linked it as disassembly/emulator evidence and kept it distinct from the firmware 13.60 console probes and direct Net hardware testing. #9525/#9542 are now fulfilled prerequisites. The new socket-record intersection with #10502 is recorded as a proposed landing order, pending its author's response.

@milescoviello

Copy link
Copy Markdown
Contributor

@Queuse a retail data point for the TCP options, in case it helps scope this.

I read the level and optname arguments at every sceNetSetsockopt call site in ten PS5 titles' relinked executables: Borderlands 4, Ghost of Tsushima, Forspoken, Metal Gear Solid 4, Astro Bot, Crimson Desert, MXGP 26, Super Meat Boy 3D, Call of Duty: Black Ops II and Steins;Gate Re:Boot. At the TCP level (6), they set:

  • TCP_NODELAY (1): one call site each in Borderlands 4, Metal Gear Solid 4, Astro Bot, Crimson Desert, MXGP 26 and Super Meat Boy 3D;
  • option 128 (FreeBSD's TCP_KEEPINIT): one call site in Borderlands 4 (PPSA01494 01.100.002).

None of them sets TCP_MAXSEG, TCP_KEEPIDLE, TCP_KEEPINTVL or TCP_KEEPCNT with a constant option. So the one other TCP option a title here asks for, TCP_KEEPINIT, still gets ENOPROTOOPT with this PR, as on main. I haven't traced what Borderlands 4 does with that result.

AI-assisted: yes (Claude Code)

@Queuse

Queuse commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for checking the retail call sites. That does not change the scope of this PR: TCP_KEEPINIT (0x80) remains unsupported and covered by the existing unsupported-TCP-options debt entry. I have not inferred its semantics, ignored its error or claimed that these changes unblock Borderlands 4. The current head stays 552191fe9c; the call-site observations are distinct from measurements of option behavior.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 28, 2026
@Queuse

Queuse commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

#10502 has merged. I resolved its actual socket-record conflict and pushed 53d19a3d87, retaining both its name field/diagnostics and the four TCP fields with accept inheritance. All eight rebuilt focused Windows tests pass, including guest_sce_net; headers, registration, conventions and whitespace pass.

The description records the exact tested main dacca6bb88, the later clean trial merge with 4a6693acf8, and the fresh overlap limits. #9948 has a debt-only intersection; I proposed #11272-first there and am keeping that as pending until confirmed. The other comparisons do not certify combined runtime behavior. TCP_KEEPINIT/title compatibility remains outside this change.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants