diff --git a/pkg/network/ebpf/c/tracer/events.h b/pkg/network/ebpf/c/tracer/events.h index 6ed2f932e4a85..71e8b42d06cd5 100644 --- a/pkg/network/ebpf/c/tracer/events.h +++ b/pkg/network/ebpf/c/tracer/events.h @@ -76,6 +76,8 @@ static __always_inline void cleanup_conn(void *ctx, conn_tuple_t *tup, struct so // we don't have any stats for the connection, // so cookie is not set, set it here conn.conn_stats.cookie = get_sk_cookie(sk); + // make sure direction is set correctly + determine_connection_direction(&conn.tup, &conn.conn_stats); } conn.conn_stats.timestamp = bpf_ktime_get_ns(); diff --git a/pkg/network/ebpf/c/tracer/stats.h b/pkg/network/ebpf/c/tracer/stats.h index 992cf85355f98..3fb663daefd23 100644 --- a/pkg/network/ebpf/c/tracer/stats.h +++ b/pkg/network/ebpf/c/tracer/stats.h @@ -84,6 +84,23 @@ static __always_inline void update_protocol_classification_information(conn_tupl merge_protocol_stacks(&stats->protocol_stack, protocol_stack); } +static __always_inline void determine_connection_direction(conn_tuple_t *t, conn_stats_ts_t *conn_stats) { + if (conn_stats->direction != CONN_DIRECTION_UNKNOWN) { + return; + } + + u32 *port_count = NULL; + port_binding_t pb = {}; + pb.port = t->sport; + pb.netns = t->netns; + if (t->metadata & CONN_TYPE_TCP) { + port_count = bpf_map_lookup_elem(&port_bindings, &pb); + } else { + port_count = bpf_map_lookup_elem(&udp_port_bindings, &pb); + } + conn_stats->direction = (port_count != NULL && *port_count > 0) ? CONN_DIRECTION_INCOMING : CONN_DIRECTION_OUTGOING; +} + // update_conn_stats update the connection metadata : protocol, tags, timestamp, direction, packets, bytes sent and received static __always_inline void update_conn_stats(conn_tuple_t *t, size_t sent_bytes, size_t recv_bytes, u64 ts, conn_direction_t dir, __u32 packets_out, __u32 packets_in, packet_count_increment_t segs_type, struct sock *sk) { @@ -121,17 +138,8 @@ static __always_inline void update_conn_stats(conn_tuple_t *t, size_t sent_bytes if (dir != CONN_DIRECTION_UNKNOWN) { val->direction = dir; - } else if (val->direction == CONN_DIRECTION_UNKNOWN) { - u32 *port_count = NULL; - port_binding_t pb = {}; - pb.port = t->sport; - pb.netns = t->netns; - if (t->metadata & CONN_TYPE_TCP) { - port_count = bpf_map_lookup_elem(&port_bindings, &pb); - } else { - port_count = bpf_map_lookup_elem(&udp_port_bindings, &pb); - } - val->direction = (port_count != NULL && *port_count > 0) ? CONN_DIRECTION_INCOMING : CONN_DIRECTION_OUTGOING; + } else { + determine_connection_direction(t, val); } } diff --git a/pkg/network/tracer/tracer_linux_test.go b/pkg/network/tracer/tracer_linux_test.go index 3ddaf05e00eb3..571e15abe5a45 100644 --- a/pkg/network/tracer/tracer_linux_test.go +++ b/pkg/network/tracer/tracer_linux_test.go @@ -1788,6 +1788,46 @@ func (s *TracerSuite) TestPreexistingConnectionDirection() { assert.Equal(t, network.INCOMING, incoming.Direction) } +func (s *TracerSuite) TestPreexistingEmptyIncomingConnectionDirection() { + t := s.T() + // Start the client and server before we enable the system probe to test that the tracer picks + // up the pre-existing connection + + ch := make(chan struct{}) + server := NewTCPServer(func(c net.Conn) { + <-ch + c.Close() + }) + require.NoError(t, server.Run()) + t.Cleanup(server.Shutdown) + + c, err := net.DialTimeout("tcp", server.address, 5*time.Second) + require.NoError(t, err) + + // Enable BPF-based system probe + tr := setupTracer(t, testConfig()) + + // close the server connection so the tracer picks it up + close(ch) + + var conn *network.ConnectionStats + require.Eventually(t, func() bool { + conns := getConnections(t, tr) + t.Log(conns) // for debugging failures + conn, _ = findConnection(c.RemoteAddr(), c.LocalAddr(), conns) + return conn != nil + }, 3*time.Second, 100*time.Millisecond) + + m := conn.Monotonic + assert.Zero(t, m.SentBytes, "sent bytes should be 0") + assert.Zero(t, m.RecvBytes, "recv bytes should be 0") + assert.Zero(t, m.SentPackets, "sent packets should be 0") + assert.Zero(t, m.RecvPackets, "recv packets should be 0") + assert.Zero(t, m.TCPEstablished, "tcp established should be 0") + assert.Equal(t, uint32(1), m.TCPClosed, "tcp closed should be 1") + assert.Equal(t, network.INCOMING, conn.Direction, "connection direction should be incoming") +} + func (s *TracerSuite) TestUDPIncomingDirectionFix() { t := s.T()