diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-19 10:32:32 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-19 10:32:32 +0300 |
| commit | 9cc2c7b3c4c7a1f1837a4a5260f11ccea5814c83 (patch) | |
| tree | 423ab8233039f23bee0d4fbcb98a0b0a68841476 | |
| parent | 127516b4bf63dc922df222825a9a6a1d7eacc214 (diff) | |
u6: fix socketpair exit fd capture and socket filtering
| -rw-r--r-- | cmd/ioworkload/scenario_socket.go | 4 | ||||
| -rw-r--r-- | integrationtests/socket_test.go | 58 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints.c | 53 | ||||
| -rw-r--r-- | internal/c/generated_tracepoints_result.txt | 2 | ||||
| -rw-r--r-- | internal/c/maps.h | 14 | ||||
| -rw-r--r-- | internal/c/types.h | 1 | ||||
| -rw-r--r-- | internal/eventloop_exit.go | 33 | ||||
| -rw-r--r-- | internal/eventloop_runtime.go | 7 | ||||
| -rw-r--r-- | internal/eventloop_socket_test.go | 52 | ||||
| -rw-r--r-- | internal/generate/bpfhandler.go | 9 | ||||
| -rw-r--r-- | internal/generate/classify.go | 2 | ||||
| -rw-r--r-- | internal/generate/classify_test.go | 7 | ||||
| -rw-r--r-- | internal/generate/codegen_test.go | 15 | ||||
| -rw-r--r-- | internal/types/fastdecode.go | 12 | ||||
| -rw-r--r-- | internal/types/fastdecode_test.go | 42 | ||||
| -rw-r--r-- | internal/types/generated_types.go | 5 | ||||
| -rw-r--r-- | internal/types/types_test.go | 2 |
17 files changed, 270 insertions, 48 deletions
diff --git a/cmd/ioworkload/scenario_socket.go b/cmd/ioworkload/scenario_socket.go index 1ffc784..f633186 100644 --- a/cmd/ioworkload/scenario_socket.go +++ b/cmd/ioworkload/scenario_socket.go @@ -6,7 +6,7 @@ import ( ) func socketBasic() error { - fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) + fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { return fmt.Errorf("socket: %w", err) } @@ -17,7 +17,7 @@ func socketBasic() error { } func socketpairBasic() error { - fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) + fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { return fmt.Errorf("socketpair: %w", err) } diff --git a/integrationtests/socket_test.go b/integrationtests/socket_test.go index a48d628..481ca86 100644 --- a/integrationtests/socket_test.go +++ b/integrationtests/socket_test.go @@ -1,21 +1,73 @@ package integrationtests -import "testing" +import ( + "strings" + "testing" +) func TestSocketBasic(t *testing.T) { - runScenario(t, "socket-basic", []ExpectedEvent{ + result, _ := runScenarioResult(t, "socket-basic", []ExpectedEvent{ { Tracepoint: "enter_socket", MinCount: 1, }, + { + Tracepoint: "enter_close", + MinCount: 1, + }, }) + + assertTracepointPathPrefix(t, result, "enter_socket", "socket:1:") + assertTracepointPathPrefix(t, result, "enter_close", "socket:1:") } func TestSocketpairBasic(t *testing.T) { - runScenario(t, "socketpair-basic", []ExpectedEvent{ + result, _ := runScenarioResult(t, "socketpair-basic", []ExpectedEvent{ { Tracepoint: "enter_socketpair", MinCount: 1, }, + { + Tracepoint: "enter_close", + MinCount: 2, + }, }) + + assertTracepointPathPrefix(t, result, "enter_socketpair", "socket:1:") + if got := totalTracepointPathCount(result, "enter_close", "socket:1:"); got < 2 { + t.Fatalf("enter_close records with tracked socket descriptor prefix = %d, want >= 2", got) + } +} + +func assertTracepointPathPrefix(t *testing.T, result TestResult, tracepoint, wantPrefix string) { + t.Helper() + if got := countTracepointPathPrefix(result, tracepoint, wantPrefix); got == 0 { + t.Fatalf("expected at least one %s record with path prefix %q", tracepoint, wantPrefix) + } +} + +func countTracepointPathPrefix(result TestResult, tracepoint, wantPrefix string) int { + var count int + for _, rec := range result.Records { + if !strings.Contains(rec.TraceID.String(), tracepoint) { + continue + } + if strings.HasPrefix(rec.Path, wantPrefix) { + count++ + } + } + return count +} + +func totalTracepointPathCount(result TestResult, tracepoint, wantPrefix string) uint64 { + var total uint64 + for _, rec := range result.Records { + if !strings.Contains(rec.TraceID.String(), tracepoint) { + continue + } + if strings.HasPrefix(rec.Path, wantPrefix) { + total += rec.Cnt.Count + } + } + return total } diff --git a/internal/c/generated_tracepoints.c b/internal/c/generated_tracepoints.c index 0974d77..03cf2b4 100644 --- a/internal/c/generated_tracepoints.c +++ b/internal/c/generated_tracepoints.c @@ -799,39 +799,64 @@ int handle_sys_enter_socketpair(struct syscall_trace_enter *ctx) { ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); - int sv[2]; - __builtin_memset(&sv, 0xff, sizeof(sv)); - if (ctx->args[3] != 0) { - bpf_probe_read_user(&sv, sizeof(sv), (void *)ctx->args[3]); - } - ev->family = (__s32)ctx->args[0]; - ev->type = (__s32)ctx->args[1]; - ev->protocol = (__s32)ctx->args[2]; - ev->sv0 = (__s32)sv[0]; - ev->sv1 = (__s32)sv[1]; + struct socketpair_ctx pending; + pending.usockvec = ctx->args[3]; + pending.family = (__s32)ctx->args[0]; + pending.type = (__s32)ctx->args[1]; + pending.protocol = (__s32)ctx->args[2]; + bpf_map_update_elem(&socketpair_ctx_map, &tid, &pending, BPF_ANY); + ev->family = pending.family; + ev->type = pending.type; + ev->protocol = pending.protocol; + ev->sv0 = -1; + ev->sv1 = -1; + ev->ret = 0; bpf_ringbuf_submit(ev, 0); return 0; } -/// sys_exit_socketpair is a struct ret_event (UNCLASSIFIED) +/// sys_exit_socketpair is a struct socketpair_event SEC("tracepoint/syscalls/sys_exit_socketpair") int handle_sys_exit_socketpair(struct syscall_trace_exit *ctx) { __u32 pid, tid; if (filter(&pid, &tid)) return 0; - struct ret_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct ret_event), 0); + struct socketpair_event *ev = bpf_ringbuf_reserve(&event_map, sizeof(struct socketpair_event), 0); if (!ev) return 0; - ev->event_type = EXIT_RET_EVENT; + ev->event_type = EXIT_SOCKETPAIR_EVENT; ev->trace_id = SYS_EXIT_SOCKETPAIR; ev->pid = pid; ev->tid = tid; ev->time = bpf_ktime_get_boot_ns(); + __s32 family = -1; + __s32 type = -1; + __s32 protocol = -1; + __s32 sv0 = -1; + __s32 sv1 = -1; + struct socketpair_ctx *pending = bpf_map_lookup_elem(&socketpair_ctx_map, &tid); + if (pending) { + family = pending->family; + type = pending->type; + protocol = pending->protocol; + if (ctx->ret == 0 && pending->usockvec != 0) { + int sv[2]; + if (bpf_probe_read_user(&sv, sizeof(sv), (void *)pending->usockvec) == 0) { + sv0 = (__s32)sv[0]; + sv1 = (__s32)sv[1]; + } + } + bpf_map_delete_elem(&socketpair_ctx_map, &tid); + } + ev->family = family; + ev->type = type; + ev->protocol = protocol; + ev->sv0 = sv0; + ev->sv1 = sv1; ev->ret = ctx->ret; - ev->ret_type = UNCLASSIFIED; bpf_ringbuf_submit(ev, 0); return 0; diff --git a/internal/c/generated_tracepoints_result.txt b/internal/c/generated_tracepoints_result.txt index 2d6e54c..560e24b 100644 --- a/internal/c/generated_tracepoints_result.txt +++ b/internal/c/generated_tracepoints_result.txt @@ -684,7 +684,7 @@ sys_exit_sigaltstack is a struct ret_event (UNCLASSIFIED) sys_exit_signalfd is a struct ret_event (UNCLASSIFIED) sys_exit_signalfd4 is a struct ret_event (UNCLASSIFIED) sys_exit_socket is a struct ret_event (UNCLASSIFIED) -sys_exit_socketpair is a struct ret_event (UNCLASSIFIED) +sys_exit_socketpair is a struct socketpair_event sys_exit_splice is a struct ret_event (TRANSFER_CLASSIFIED) sys_exit_statfs is a struct ret_event (UNCLASSIFIED) sys_exit_statmount is a struct ret_event (UNCLASSIFIED) diff --git a/internal/c/maps.h b/internal/c/maps.h index 7ec871c..1624ff8 100644 --- a/internal/c/maps.h +++ b/internal/c/maps.h @@ -4,3 +4,17 @@ struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries, 1 << 24); } event_map SEC(".maps"); + +struct socketpair_ctx { + __u64 usockvec; + __s32 family; + __s32 type; + __s32 protocol; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 8192); + __type(key, __u32); + __type(value, struct socketpair_ctx); +} socketpair_ctx_map SEC(".maps"); diff --git a/internal/c/types.h b/internal/c/types.h index ddb2dca..29f18e1 100644 --- a/internal/c/types.h +++ b/internal/c/types.h @@ -141,4 +141,5 @@ struct socketpair_event { __s32 protocol; __s32 sv0; __s32 sv1; + __s64 ret; }; diff --git a/internal/eventloop_exit.go b/internal/eventloop_exit.go index e13d3c5..c64515b 100644 --- a/internal/eventloop_exit.go +++ b/internal/eventloop_exit.go @@ -233,25 +233,42 @@ func (e *eventLoop) handleSocketExit(ep *event.Pair, socketEv *types.SocketEvent ep.File = fdFile } ep.Comm = e.comm(socketEv.GetTid()) + if !e.Filter().MatchPair(ep) { + ep.Recycle() + return false + } return true } func (e *eventLoop) handleSocketpairExit(ep *event.Pair, socketpairEv *types.SocketpairEvent) bool { - retEvent, ok := ep.ExitEv.(*types.RetEvent) + exitEv, ok := ep.ExitEv.(*types.SocketpairEvent) if !ok { e.recyclePair(ep, "Dropped malformed socketpair exit event") return false } - if retEvent.Ret == 0 { - if socketpairEv.Sv0 >= 0 { - fdFile := file.NewFd(socketpairEv.Sv0, socketDescriptorName(socketpairEv.Family, socketpairEv.Type, socketpairEv.Protocol), -1) - e.fdState().set(socketpairEv.Sv0, fdFile) + family := exitEv.Family + typ := exitEv.Type + protocol := exitEv.Protocol + if family < 0 { + family = socketpairEv.Family + } + if typ < 0 { + typ = socketpairEv.Type + } + if protocol < 0 { + protocol = socketpairEv.Protocol + } + + if exitEv.Ret == 0 { + if exitEv.Sv0 >= 0 { + fdFile := file.NewFd(exitEv.Sv0, socketDescriptorName(family, typ, protocol), -1) + e.fdState().set(exitEv.Sv0, fdFile) ep.File = fdFile } - if socketpairEv.Sv1 >= 0 { - fdFile := file.NewFd(socketpairEv.Sv1, socketDescriptorName(socketpairEv.Family, socketpairEv.Type, socketpairEv.Protocol), -1) - e.fdState().set(socketpairEv.Sv1, fdFile) + if exitEv.Sv1 >= 0 { + fdFile := file.NewFd(exitEv.Sv1, socketDescriptorName(family, typ, protocol), -1) + e.fdState().set(exitEv.Sv1, fdFile) if ep.File == nil { ep.File = fdFile } diff --git a/internal/eventloop_runtime.go b/internal/eventloop_runtime.go index d9acb23..55948bc 100644 --- a/internal/eventloop_runtime.go +++ b/internal/eventloop_runtime.go @@ -278,6 +278,13 @@ func (e *eventLoop) registerSocketHandlers() { } e.tracepointEntered(socketpairEv) } + e.rawHandlers[types.EXIT_SOCKETPAIR_EVENT] = func(raw []byte, ch chan<- *event.Pair) { + socketpairEv, ok := decodeRawEvent(e, types.EXIT_SOCKETPAIR_EVENT, raw, types.NewSocketpairEventFast) + if !ok { + return + } + e.tracepointExited(socketpairEv, ch) + } } func decodeRawEvent[T any](e *eventLoop, eventType types.EventType, raw []byte, decode func([]byte) *T) (*T, bool) { diff --git a/internal/eventloop_socket_test.go b/internal/eventloop_socket_test.go index 6b76813..7712b3c 100644 --- a/internal/eventloop_socket_test.go +++ b/internal/eventloop_socket_test.go @@ -4,6 +4,7 @@ import ( "testing" "ior/internal/event" + "ior/internal/globalfilter" "ior/internal/types" ) @@ -36,7 +37,39 @@ func TestHandleSocketExitTracksReturnedFd(t *testing.T) { verifyFileDescriptor(t, el, 55, "socket:1:2:0") } -func TestHandleSocketpairExitTracksReturnedFds(t *testing.T) { +func TestHandleSocketExitAppliesPairFilter(t *testing.T) { + el := mustNewEventLoop(t, eventLoopConfig{ + filter: globalfilter.Filter{ + Syscall: &globalfilter.StringFilter{Pattern: "openat"}, + }, + }) + + enter := &types.SocketEvent{ + EventType: types.ENTER_SOCKET_EVENT, + TraceId: types.SYS_ENTER_SOCKET, + Time: 100, + Pid: 42, + Tid: 43, + Family: 1, + Type: 2, + Protocol: 0, + } + exit := &types.RetEvent{ + EventType: types.EXIT_SOCKET_EVENT, + TraceId: types.SYS_EXIT_SOCKET, + Time: 200, + Ret: 55, + Pid: 42, + Tid: 43, + } + ep := &event.Pair{EnterEv: enter, ExitEv: exit} + + if ok := el.handleSocketExit(ep, enter); ok { + t.Fatal("handleSocketExit should reject pair due to filter mismatch") + } +} + +func TestHandleSocketpairExitTracksReturnedFdsFromExitEvent(t *testing.T) { el := mustNewEventLoop(t, eventLoopConfig{}) enter := &types.SocketpairEvent{ @@ -48,16 +81,22 @@ func TestHandleSocketpairExitTracksReturnedFds(t *testing.T) { Family: 1, Type: 1, Protocol: 0, - Sv0: 61, - Sv1: 62, + Sv0: -1, + Sv1: -1, + Ret: 0, } - exit := &types.RetEvent{ + exit := &types.SocketpairEvent{ EventType: types.EXIT_SOCKETPAIR_EVENT, TraceId: types.SYS_EXIT_SOCKETPAIR, Time: 200, - Ret: 0, Pid: 77, Tid: 78, + Family: 1, + Type: 1, + Protocol: 0, + Sv0: 61, + Sv1: 62, + Ret: 0, } ep := &event.Pair{EnterEv: enter, ExitEv: exit} @@ -76,4 +115,7 @@ func TestInitRawHandlersRegistersSocketEvents(t *testing.T) { if _, ok := el.rawHandlers[types.ENTER_SOCKETPAIR_EVENT]; !ok { t.Fatal("ENTER_SOCKETPAIR_EVENT handler is not registered") } + if _, ok := el.rawHandlers[types.EXIT_SOCKETPAIR_EVENT]; !ok { + t.Fatal("EXIT_SOCKETPAIR_EVENT handler is not registered") + } } diff --git a/internal/generate/bpfhandler.go b/internal/generate/bpfhandler.go index 6c9c314..50917e7 100644 --- a/internal/generate/bpfhandler.go +++ b/internal/generate/bpfhandler.go @@ -76,7 +76,7 @@ func generateExtra(tp GeneratedTracepoint, isEnter bool) string { case KindSocket: return generateExtraSocket() case KindSocketpair: - return generateExtraSocketpair() + return generateExtraSocketpair(isEnter) case KindOpen: return generateExtraOpen(f) case KindPathname: @@ -157,8 +157,11 @@ func generateExtraSocket() string { return " ev->family = (__s32)ctx->args[0];\n ev->type = (__s32)ctx->args[1];\n ev->protocol = (__s32)ctx->args[2];\n" } -func generateExtraSocketpair() string { - return " int sv[2];\n __builtin_memset(&sv, 0xff, sizeof(sv));\n if (ctx->args[3] != 0) {\n bpf_probe_read_user(&sv, sizeof(sv), (void *)ctx->args[3]);\n }\n ev->family = (__s32)ctx->args[0];\n ev->type = (__s32)ctx->args[1];\n ev->protocol = (__s32)ctx->args[2];\n ev->sv0 = (__s32)sv[0];\n ev->sv1 = (__s32)sv[1];\n" +func generateExtraSocketpair(isEnter bool) string { + if isEnter { + return " struct socketpair_ctx pending;\n pending.usockvec = ctx->args[3];\n pending.family = (__s32)ctx->args[0];\n pending.type = (__s32)ctx->args[1];\n pending.protocol = (__s32)ctx->args[2];\n bpf_map_update_elem(&socketpair_ctx_map, &tid, &pending, BPF_ANY);\n ev->family = pending.family;\n ev->type = pending.type;\n ev->protocol = pending.protocol;\n ev->sv0 = -1;\n ev->sv1 = -1;\n ev->ret = 0;\n" + } + return " __s32 family = -1;\n __s32 type = -1;\n __s32 protocol = -1;\n __s32 sv0 = -1;\n __s32 sv1 = -1;\n struct socketpair_ctx *pending = bpf_map_lookup_elem(&socketpair_ctx_map, &tid);\n if (pending) {\n family = pending->family;\n type = pending->type;\n protocol = pending->protocol;\n if (ctx->ret == 0 && pending->usockvec != 0) {\n int sv[2];\n if (bpf_probe_read_user(&sv, sizeof(sv), (void *)pending->usockvec) == 0) {\n sv0 = (__s32)sv[0];\n sv1 = (__s32)sv[1];\n }\n }\n bpf_map_delete_elem(&socketpair_ctx_map, &tid);\n }\n ev->family = family;\n ev->type = type;\n ev->protocol = protocol;\n ev->sv0 = sv0;\n ev->sv1 = sv1;\n ev->ret = ctx->ret;\n" } // eventStructName returns the C struct name for a TracepointKind. The mapping diff --git a/internal/generate/classify.go b/internal/generate/classify.go index 68cd722..56f5cd2 100644 --- a/internal/generate/classify.go +++ b/internal/generate/classify.go @@ -85,6 +85,8 @@ func classifyNameOnly(name string) (ClassificationResult, bool) { return ClassificationResult{Kind: KindSocket}, true case "sys_enter_socketpair": return ClassificationResult{Kind: KindSocketpair}, true + case "sys_exit_socketpair": + return ClassificationResult{Kind: KindSocketpair}, 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 ce6eff1..e6353b5 100644 --- a/internal/generate/classify_test.go +++ b/internal/generate/classify_test.go @@ -258,6 +258,13 @@ func TestClassifySocketpair(t *testing.T) { } } +func TestClassifyExitSocketpair(t *testing.T) { + r := classifyFromData(t, FormatExitSocketpair) + if r.Kind != KindSocketpair { + t.Errorf("exit_socketpair: got kind %d, want KindSocketpair", r.Kind) + } +} + func TestClassifyKillRequiresGenerationFallback(t *testing.T) { r := classifyFromData(t, FormatKill) if r.Kind != KindNone { diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go index f87a6dc..3e29612 100644 --- a/internal/generate/codegen_test.go +++ b/internal/generate/codegen_test.go @@ -200,11 +200,16 @@ func TestGenerateSocketpairHandler(t *testing.T) { requireContains(t, output, "struct socketpair_event *ev") requireContains(t, output, "ev->event_type = ENTER_SOCKETPAIR_EVENT;") - requireContains(t, output, "int sv[2];") - requireContains(t, output, "bpf_probe_read_user(&sv, sizeof(sv), (void *)ctx->args[3]);") - requireContains(t, output, "ev->family = (__s32)ctx->args[0];") - requireContains(t, output, "ev->sv0 = (__s32)sv[0];") - requireContains(t, output, "ev->sv1 = (__s32)sv[1];") + requireContains(t, output, "struct socketpair_ctx pending;") + requireContains(t, output, "bpf_map_update_elem(&socketpair_ctx_map, &tid, &pending, BPF_ANY);") + requireContains(t, output, "ev->sv0 = -1;") + requireContains(t, output, "ev->ret = 0;") + requireContains(t, output, "SEC(\"tracepoint/syscalls/sys_exit_socketpair\")") + requireContains(t, output, "ev->event_type = EXIT_SOCKETPAIR_EVENT;") + requireContains(t, output, "struct socketpair_ctx *pending = bpf_map_lookup_elem(&socketpair_ctx_map, &tid);") + requireContains(t, output, "if (ctx->ret == 0 && pending->usockvec != 0) {") + requireContains(t, output, "ev->ret = ctx->ret;") + requireContains(t, output, "ev->family = pending.family;") } func TestGenerateNameToHandleAtHandler(t *testing.T) { diff --git a/internal/types/fastdecode.go b/internal/types/fastdecode.go index b464013..0967c02 100644 --- a/internal/types/fastdecode.go +++ b/internal/types/fastdecode.go @@ -13,7 +13,8 @@ const ( dup3EventSize = 32 openByHandleAtEventSize = 28 socketEventSize = 36 - socketpairEventSize = 44 + socketpairEventSize = 56 + socketpairEventSizeV1 = 52 ) func NewOpenEventFast(raw []byte) *OpenEvent { @@ -195,10 +196,10 @@ func NewSocketEventFast(raw []byte) *SocketEvent { } func NewSocketpairEventFast(raw []byte) *SocketpairEvent { - if len(raw) < socketpairEventSize { + if len(raw) < socketpairEventSizeV1 { return nil } - if len(raw) != socketpairEventSize { + if len(raw) != socketpairEventSize && len(raw) != socketpairEventSizeV1 { return NewSocketpairEvent(raw) } s := poolOfSocketpairEvents.Get().(*SocketpairEvent) @@ -212,5 +213,10 @@ func NewSocketpairEventFast(raw []byte) *SocketpairEvent { s.Protocol = int32(binary.LittleEndian.Uint32(raw[32:36])) s.Sv0 = int32(binary.LittleEndian.Uint32(raw[36:40])) s.Sv1 = int32(binary.LittleEndian.Uint32(raw[40:44])) + retOffset := 44 + if len(raw) == socketpairEventSize { + retOffset = 48 + } + s.Ret = int64(binary.LittleEndian.Uint64(raw[retOffset : retOffset+8])) return s } diff --git a/internal/types/fastdecode_test.go b/internal/types/fastdecode_test.go index 5279130..f15cc9e 100644 --- a/internal/types/fastdecode_test.go +++ b/internal/types/fastdecode_test.go @@ -1,6 +1,9 @@ package types -import "testing" +import ( + "encoding/binary" + "testing" +) func TestFastDecodersMatchGeneratedDecoders(t *testing.T) { t.Run("OpenEvent", func(t *testing.T) { @@ -139,7 +142,7 @@ func TestFastDecodersMatchGeneratedDecoders(t *testing.T) { }) t.Run("SocketpairEvent", func(t *testing.T) { - ev := &SocketpairEvent{EventType: ENTER_SOCKETPAIR_EVENT, TraceId: SYS_ENTER_SOCKETPAIR, Time: 1, Pid: 2, Tid: 3, Family: 1, Type: 2, Protocol: 0, Sv0: 10, Sv1: 11} + ev := &SocketpairEvent{EventType: ENTER_SOCKETPAIR_EVENT, TraceId: SYS_ENTER_SOCKETPAIR, Time: 1, Pid: 2, Tid: 3, Family: 1, Type: 2, Protocol: 0, Sv0: 10, Sv1: 11, Ret: -1} raw, _ := ev.Bytes() slow := NewSocketpairEvent(raw) @@ -152,6 +155,41 @@ func TestFastDecodersMatchGeneratedDecoders(t *testing.T) { }) } +func TestNewSocketpairEventFastKernelLayout(t *testing.T) { + raw := make([]byte, socketpairEventSize) + binary.LittleEndian.PutUint32(raw[0:4], uint32(ENTER_SOCKETPAIR_EVENT)) + binary.LittleEndian.PutUint32(raw[4:8], uint32(SYS_ENTER_SOCKETPAIR)) + binary.LittleEndian.PutUint64(raw[8:16], 1) + binary.LittleEndian.PutUint32(raw[16:20], 2) + binary.LittleEndian.PutUint32(raw[20:24], 3) + binary.LittleEndian.PutUint32(raw[24:28], uint32(1)) + binary.LittleEndian.PutUint32(raw[28:32], uint32(2)) + binary.LittleEndian.PutUint32(raw[32:36], uint32(0)) + binary.LittleEndian.PutUint32(raw[36:40], uint32(10)) + binary.LittleEndian.PutUint32(raw[40:44], uint32(11)) + binary.LittleEndian.PutUint64(raw[48:56], uint64(0)) + + fast := NewSocketpairEventFast(raw) + if fast == nil { + t.Fatalf("expected decoded socketpair event for kernel layout payload") + } + defer fast.Recycle() + + if fast.EventType != ENTER_SOCKETPAIR_EVENT || + fast.TraceId != SYS_ENTER_SOCKETPAIR || + fast.Time != 1 || + fast.Pid != 2 || + fast.Tid != 3 || + fast.Family != 1 || + fast.Type != 2 || + fast.Protocol != 0 || + fast.Sv0 != 10 || + fast.Sv1 != 11 || + fast.Ret != 0 { + t.Fatalf("unexpected socketpair decode: %#v", fast) + } +} + func TestFastDecodersReturnNilOnShortPayload(t *testing.T) { cases := []struct { name string diff --git a/internal/types/generated_types.go b/internal/types/generated_types.go index fb4dd36..bdfce73 100644 --- a/internal/types/generated_types.go +++ b/internal/types/generated_types.go @@ -1528,10 +1528,11 @@ type SocketpairEvent struct { Protocol int32 Sv0 int32 Sv1 int32 + Ret int64 } func (s SocketpairEvent) String() string { - return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Family:%v Type:%v Protocol:%v Sv0:%v Sv1:%v", s.EventType, s.TraceId, s.Time, s.Pid, s.Tid, s.Family, s.Type, s.Protocol, s.Sv0, s.Sv1) + return fmt.Sprintf("EventType:%v TraceId:%v Time:%v Pid:%v Tid:%v Family:%v Type:%v Protocol:%v Sv0:%v Sv1:%v Ret:%v", s.EventType, s.TraceId, s.Time, s.Pid, s.Tid, s.Family, s.Type, s.Protocol, s.Sv0, s.Sv1, s.Ret) } func (s SocketpairEvent) Equals(other any) bool { @@ -1539,7 +1540,7 @@ func (s SocketpairEvent) Equals(other any) bool { if !ok { return false } - return s.EventType == otherConcrete.EventType && s.TraceId == otherConcrete.TraceId && s.Time == otherConcrete.Time && s.Pid == otherConcrete.Pid && s.Tid == otherConcrete.Tid && s.Family == otherConcrete.Family && s.Type == otherConcrete.Type && s.Protocol == otherConcrete.Protocol && s.Sv0 == otherConcrete.Sv0 && s.Sv1 == otherConcrete.Sv1 + return s.EventType == otherConcrete.EventType && s.TraceId == otherConcrete.TraceId && s.Time == otherConcrete.Time && s.Pid == otherConcrete.Pid && s.Tid == otherConcrete.Tid && s.Family == otherConcrete.Family && s.Type == otherConcrete.Type && s.Protocol == otherConcrete.Protocol && s.Sv0 == otherConcrete.Sv0 && s.Sv1 == otherConcrete.Sv1 && s.Ret == otherConcrete.Ret } func (s *SocketpairEvent) GetEventType() EventType { diff --git a/internal/types/types_test.go b/internal/types/types_test.go index 9e11baa..40b5090 100644 --- a/internal/types/types_test.go +++ b/internal/types/types_test.go @@ -169,6 +169,7 @@ func TestSocketpairEventSerialization(t *testing.T) { Protocol: 0, Sv0: 42, Sv1: 43, + Ret: -1, } bytes, err := socketpairEv1.Bytes() if err != nil { @@ -186,6 +187,7 @@ func TestSocketpairEventSerialization(t *testing.T) { assertEquals(t, socketpairEv1.Protocol, socketpairEv2.Protocol) assertEquals(t, socketpairEv1.Sv0, socketpairEv2.Sv0) assertEquals(t, socketpairEv1.Sv1, socketpairEv2.Sv1) + assertEquals(t, socketpairEv1.Ret, socketpairEv2.Ret) } func TestEqualsDifferentTypes(t *testing.T) { |
