summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-19 15:47:09 +0300
committerPaul Buetow <paul@buetow.org>2026-05-19 15:47:09 +0300
commit061fb2b2380752eed06a78d10567da172ea8e27c (patch)
tree5d2ec93cca785a3c0dfbaa0b520d45a96e0f8c6c
parent03a3513e0d8366fb2d04e3d055a3a98b63b9e708 (diff)
w6: extend KindFd socket introspection coverage
-rw-r--r--cmd/ioworkload/scenario_socket.go54
-rw-r--r--cmd/ioworkload/scenarios.go1
-rw-r--r--integrationtests/socket_test.go14
-rw-r--r--internal/generate/classify.go8
-rw-r--r--internal/generate/classify_test.go13
5 files changed, 88 insertions, 2 deletions
diff --git a/cmd/ioworkload/scenario_socket.go b/cmd/ioworkload/scenario_socket.go
index db95ad4..420cdfb 100644
--- a/cmd/ioworkload/scenario_socket.go
+++ b/cmd/ioworkload/scenario_socket.go
@@ -120,3 +120,57 @@ func socketAcceptLifecyclePlain() error {
}
return nil
}
+
+func socketIntrospection() error {
+ dir, cleanup, err := makeTempDir("socket-introspection")
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ socketPath := filepath.Join(dir, "introspection.sock")
+
+ listenerFD, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ return fmt.Errorf("listener socket: %w", err)
+ }
+ defer syscall.Close(listenerFD) //nolint:errcheck
+
+ if err := syscall.Bind(listenerFD, &syscall.SockaddrUnix{Name: socketPath}); err != nil {
+ return fmt.Errorf("bind: %w", err)
+ }
+ if err := syscall.Listen(listenerFD, 1); err != nil {
+ return fmt.Errorf("listen: %w", err)
+ }
+
+ clientFD, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ return fmt.Errorf("client socket: %w", err)
+ }
+ defer syscall.Close(clientFD) //nolint:errcheck
+
+ if err := syscall.Connect(clientFD, &syscall.SockaddrUnix{Name: socketPath}); err != nil {
+ return fmt.Errorf("connect: %w", err)
+ }
+
+ acceptedFD, _, err := syscall.Accept4(listenerFD, 0)
+ if err != nil {
+ return fmt.Errorf("accept4: %w", err)
+ }
+ defer syscall.Close(acceptedFD) //nolint:errcheck
+
+ if _, err := syscall.Getsockname(acceptedFD); err != nil {
+ return fmt.Errorf("getsockname: %w", err)
+ }
+ if _, err := syscall.Getpeername(acceptedFD); err != nil {
+ return fmt.Errorf("getpeername: %w", err)
+ }
+ if err := syscall.SetsockoptInt(acceptedFD, syscall.SOL_SOCKET, syscall.SO_RCVBUF, 32768); err != nil {
+ return fmt.Errorf("setsockopt: %w", err)
+ }
+ if _, err := syscall.GetsockoptInt(acceptedFD, syscall.SOL_SOCKET, syscall.SO_RCVBUF); err != nil {
+ return fmt.Errorf("getsockopt: %w", err)
+ }
+
+ return nil
+}
diff --git a/cmd/ioworkload/scenarios.go b/cmd/ioworkload/scenarios.go
index 5648801..9700d85 100644
--- a/cmd/ioworkload/scenarios.go
+++ b/cmd/ioworkload/scenarios.go
@@ -29,6 +29,7 @@ var scenarios = map[string]func() error{
"socketpair-basic": socketpairBasic,
"socket-accept-lifecycle": socketAcceptLifecycle,
"socket-accept-lifecycle-plain": socketAcceptLifecyclePlain,
+ "socket-introspection": socketIntrospection,
"family-mixed": familyMixed,
"close-basic": closeBasic,
"close-range": closeRange,
diff --git a/integrationtests/socket_test.go b/integrationtests/socket_test.go
index 4967c6e..059d339 100644
--- a/integrationtests/socket_test.go
+++ b/integrationtests/socket_test.go
@@ -75,6 +75,20 @@ func TestSocketAcceptLifecyclePlain(t *testing.T) {
})
}
+func TestSocketIntrospection(t *testing.T) {
+ result, _ := runScenarioResult(t, "socket-introspection", []ExpectedEvent{
+ {Tracepoint: "enter_getsockname", MinCount: 1},
+ {Tracepoint: "enter_getpeername", MinCount: 1},
+ {Tracepoint: "enter_setsockopt", MinCount: 1},
+ {Tracepoint: "enter_getsockopt", MinCount: 1},
+ })
+
+ assertTracepointPathPrefix(t, result, "enter_getsockname", "socket:1:")
+ assertTracepointPathPrefix(t, result, "enter_getpeername", "socket:1:")
+ assertTracepointPathPrefix(t, result, "enter_setsockopt", "socket:1:")
+ assertTracepointPathPrefix(t, result, "enter_getsockopt", "socket:1:")
+}
+
func assertTracepointPathPrefix(t *testing.T, result TestResult, tracepoint, wantPrefix string) {
t.Helper()
if got := countTracepointPathPrefix(result, tracepoint, wantPrefix); got == 0 {
diff --git a/internal/generate/classify.go b/internal/generate/classify.go
index abe6b2e..4f6d14c 100644
--- a/internal/generate/classify.go
+++ b/internal/generate/classify.go
@@ -104,6 +104,14 @@ func classifyNameOnly(name string) (ClassificationResult, bool) {
return ClassificationResult{Kind: KindFd}, true
case "sys_enter_shutdown":
return ClassificationResult{Kind: KindFd}, true
+ case "sys_enter_getsockname":
+ return ClassificationResult{Kind: KindFd}, true
+ case "sys_enter_getpeername":
+ return ClassificationResult{Kind: KindFd}, true
+ case "sys_enter_getsockopt":
+ return ClassificationResult{Kind: KindFd}, true
+ case "sys_enter_setsockopt":
+ return ClassificationResult{Kind: KindFd}, true
}
if strings.HasPrefix(name, "sys_enter_io_") {
return ClassificationResult{Kind: KindNull}, true
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index 07cfe49..5c7111f 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -265,8 +265,17 @@ func TestClassifyExitAccept4(t *testing.T) {
}
}
-func TestClassifySocketLifecycleFdSyscallsByName(t *testing.T) {
- tests := []string{"bind", "connect", "listen", "shutdown"}
+func TestClassifySocketFdSyscallsByName(t *testing.T) {
+ tests := []string{
+ "bind",
+ "connect",
+ "listen",
+ "shutdown",
+ "getsockname",
+ "getpeername",
+ "getsockopt",
+ "setsockopt",
+ }
for _, name := range tests {
t.Run(name, func(t *testing.T) {
r := ClassifyFormat(&Format{