You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by wu...@apache.org on 2023/12/25 14:42:28 UTC

(skywalking-rover) branch main updated: Support collecting the access log from Kubernetes (#107)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-rover.git


The following commit(s) were added to refs/heads/main by this push:
     new c979bbf  Support collecting the access log from Kubernetes (#107)
c979bbf is described below

commit c979bbf0271b37bfb68f531b2140afe55f634072
Author: mrproliu <74...@qq.com>
AuthorDate: Mon Dec 25 22:42:23 2023 +0800

    Support collecting the access log from Kubernetes (#107)
---
 CHANGES.md                                         |   1 +
 bpf/accesslog/accesslog.c                          |  59 ++
 bpf/accesslog/common/connection.h                  | 322 +++++++++++
 bpf/accesslog/common/data_args.h                   | 110 ++++
 .../continuous/skb.h => accesslog/common/sock.h}   |  40 +-
 bpf/accesslog/l24/l24.h                            | 139 +++++
 bpf/accesslog/l24/nf.c                             |  54 ++
 .../register.go => bpf/accesslog/l24/read_l2.c     |  34 +-
 bpf/accesslog/l24/read_l3.c                        | 176 ++++++
 bpf/accesslog/l24/read_l4.c                        |  59 ++
 bpf/accesslog/l24/write_l2.c                       |  72 +++
 bpf/accesslog/l24/write_l3.c                       | 147 +++++
 bpf/accesslog/l24/write_l4.c                       | 103 ++++
 .../network.go => bpf/accesslog/process/process.c  |  67 +--
 .../protocol.go => bpf/accesslog/process/process.h |  20 +-
 bpf/accesslog/syscalls/close.c                     |  70 +++
 bpf/accesslog/syscalls/connect.c                   | 149 +++++
 bpf/accesslog/syscalls/connect_conntrack.c         | 117 ++++
 bpf/accesslog/syscalls/connect_conntrack.h         |  99 ++++
 bpf/accesslog/syscalls/transfer.c                  | 634 +++++++++++++++++++++
 bpf/accesslog/syscalls/transfer.h                  | 352 ++++++++++++
 bpf/accesslog/tls/go_tls.c                         | 195 +++++++
 bpf/accesslog/tls/go_tls.h                         |  49 ++
 bpf/accesslog/tls/node_tls.c                       |  50 ++
 bpf/accesslog/tls/node_tls.h                       |  79 +++
 bpf/accesslog/tls/openssl.c                        | 132 +++++
 .../protocol.go => bpf/accesslog/tls/openssl.h     |   8 -
 .../enums/protocol.go => bpf/accesslog/tls/tls.h   |  16 +-
 bpf/include/list.h                                 | 102 ++++
 bpf/include/protocol_analyzer.h                    |  16 +
 bpf/{profiling/network => include}/socket.h        |  29 +-
 bpf/include/socket_opts.h                          |  57 ++
 bpf/include/socket_reader.h                        |  64 +++
 bpf/profiling/continuous/network.c                 |   9 +-
 bpf/profiling/continuous/network.h                 |   9 +-
 bpf/profiling/network/args.h                       |  36 +-
 configs/rover_configs.yaml                         |  18 +-
 go.mod                                             |  12 +-
 go.sum                                             |  28 +-
 .../host/network.go => accesslog/bpf/loader.go}    |  56 +-
 pkg/accesslog/collector/close.go                   |  56 ++
 .../skb.h => pkg/accesslog/collector/collector.go  |  41 +-
 pkg/accesslog/collector/connect.go                 | 162 ++++++
 pkg/accesslog/collector/l24.go                     |  93 +++
 .../register.go => accesslog/collector/process.go} |  41 +-
 pkg/accesslog/collector/protocols/http1.go         | 234 ++++++++
 pkg/accesslog/collector/protocols/http2.go         | 314 ++++++++++
 pkg/accesslog/collector/protocols/protocol.go      |  92 +++
 pkg/accesslog/collector/protocols/queue.go         | 282 +++++++++
 pkg/accesslog/collector/tls.go                     |  87 +++
 pkg/accesslog/collector/transfer.go                |  77 +++
 .../process.go => accesslog/common/accesslog.go}   |  27 +-
 .../base/process.go => accesslog/common/config.go} |  42 +-
 pkg/accesslog/common/connection.go                 | 447 +++++++++++++++
 pkg/accesslog/common/queue.go                      | 141 +++++
 .../enums/protocol.go => accesslog/common/type.go} |   9 +-
 .../enums/protocol.go => accesslog/events/base.go} |  17 +-
 .../register.go => accesslog/events/close.go}      |  37 +-
 pkg/accesslog/events/connect.go                    |  59 ++
 .../network/analyze => accesslog}/events/data.go   |  73 +--
 pkg/accesslog/events/detail.go                     |  73 +++
 .../network.go => accesslog/forwarder/close.go}    |  50 +-
 pkg/accesslog/forwarder/connect.go                 |  64 +++
 .../forwarder/forwarder.go}                        |  53 +-
 .../enums => accesslog/forwarder}/protocol.go      |  14 +-
 pkg/accesslog/forwarder/transfer.go                | 141 +++++
 pkg/{process => accesslog}/module.go               |  56 +-
 pkg/accesslog/runner.go                            | 321 +++++++++++
 pkg/boot/register.go                               |   2 +
 pkg/process/api.go                                 |   7 +
 pkg/process/api/process.go                         |  22 +
 pkg/process/finders/base/finder.go                 |  15 +-
 pkg/process/finders/context.go                     |  11 +-
 pkg/process/finders/kubernetes/finder.go           | 104 ++--
 pkg/process/finders/kubernetes/process.go          |   8 +
 pkg/process/finders/manager.go                     |  27 +-
 pkg/process/finders/scanner/finder.go              |  82 ++-
 pkg/process/finders/scanner/process.go             |  18 +-
 pkg/process/finders/storage.go                     |  13 +-
 pkg/process/module.go                              |   8 +
 .../continuous/checker/bpf/network/reader.go       |  10 +-
 .../task/network/analyze/base/connection.go        |  10 +-
 pkg/profiling/task/network/analyze/base/context.go |  44 +-
 pkg/profiling/task/network/analyze/base/metrics.go |   8 +-
 .../task/network/analyze/base/tcpresolver.go       | 155 -----
 pkg/profiling/task/network/analyze/base/traffic.go |  38 +-
 pkg/profiling/task/network/analyze/events/data.go  |  66 +--
 .../task/network/analyze/events/sockets.go         |   8 +-
 .../task/network/analyze/layer4/events.go          |   8 +-
 .../task/network/analyze/layer4/listener.go        |  15 +-
 .../task/network/analyze/layer7/listener.go        |   3 +-
 .../analyze/layer7/protocols/base/analyzer.go      |   8 +-
 .../analyze/layer7/protocols/base/protocol.go      |   9 +-
 .../analyze/layer7/protocols/http1/analyzer.go     |  17 +-
 .../analyze/layer7/protocols/http1/metrics.go      |  21 +-
 .../layer7/protocols/http1/reader/reader.go        |   8 +-
 .../layer7/protocols/http1/reader/request.go       |   6 +-
 .../layer7/protocols/http1/reader/response.go      |   4 +-
 .../analyze/layer7/protocols/http1/sampling.go     |   2 +-
 .../network/analyze/layer7/protocols/protocols.go  |  11 +-
 pkg/tools/btf/linker.go                            |   3 +
 .../network/analyze => tools}/buffer/buffer.go     | 228 ++++++--
 .../analyze => tools}/buffer/buffer_test.go        |   0
 .../network/analyze => tools}/enums/protocol.go    |   0
 .../events/enums.go => tools/enums/socket.go}      |  34 +-
 pkg/tools/host/network.go                          |   8 +-
 pkg/tools/ip.go                                    |   6 -
 .../analyze/enums/protocol.go => tools/ip/bpf.go}  |  18 +-
 pkg/tools/ip/tcpresolver.go                        |  60 ++
 pkg/tools/ssl/gotls.go                             |  18 +-
 .../protocols/base => tools/tracing}/tracing.go    |  31 +-
 111 files changed, 7109 insertions(+), 957 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 9ea818f..cc9b323 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@ Release Notes.
 * Add `HasOwnerName` to judgement pod has owner name.
 * Publish the `latest` Docker image tag.
 * Improve the stability of Off CPU Profiling.
+* Support collecting the access log from Kubernetes.
 
 #### Bug Fixes
 
diff --git a/bpf/accesslog/accesslog.c b/bpf/accesslog/accesslog.c
new file mode 100644
index 0000000..87b62dd
--- /dev/null
+++ b/bpf/accesslog/accesslog.c
@@ -0,0 +1,59 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <bpf/bpf_endian.h>
+#include "api.h"
+#include "syscall_reading.h"
+#include "protocol_analyzer.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/sched.h>
+#include <linux/bpf.h>
+#include <linux/ptrace.h>
+#include <linux/socket.h>
+#include <asm/errno.h>
+#include <arpa/inet.h>
+#include <bpf/bpf_endian.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+
+char __license[] SEC("license") = "Dual MIT/GPL";
+
+// process execution monitoring
+#include "process/process.c"
+
+// syscalls monitoring
+#include "syscalls/connect.c"
+#include "syscalls/transfer.c"
+#include "syscalls/close.c"
+
+// network l2-l4 monitoring
+#include "l24/write_l4.c"
+#include "l24/write_l3.c"
+#include "l24/write_l2.c"
+#include "l24/nf.c"
+#include "l24/read_l4.c"
+#include "l24/read_l3.c"
+#include "l24/read_l2.c"
+
+// tls monitoring
+#include "tls/go_tls.c"
+#include "tls/node_tls.c"
+#include "tls/openssl.c"
\ No newline at end of file
diff --git a/bpf/accesslog/common/connection.h b/bpf/accesslog/common/connection.h
new file mode 100644
index 0000000..eb51267
--- /dev/null
+++ b/bpf/accesslog/common/connection.h
@@ -0,0 +1,322 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "api.h"
+#include "socket.h"
+#include "data_args.h"
+#include "socket_opts.h"
+
+// syscall:connect
+struct connect_args_t {
+    __u32 fd;
+    __u32 fix;
+    struct sockaddr* addr;
+    struct sock *sock;
+    __u64 start_nacs;
+
+    struct connect_track_remote remote;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct connect_args_t);
+} conecting_args SEC(".maps");
+
+// syscall:accept
+struct accept_args_t {
+    struct sockaddr* addr;
+    struct socket* socket;
+    __u64 start_nacs;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct accept_args_t);
+} accepting_args SEC(".maps");
+
+// syscall:close
+struct sock_close_args_t {
+    int fd;
+    __u64 start_nacs;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct sock_close_args_t);
+} closing_args SEC(".maps");
+
+// notify to the user-space the connection connected(connect, accept)
+// only traced connection ipv4/v6 or unknown connection
+struct socket_connect_event_t {
+    // current connection id
+    __u64 conid;
+    // random value in one active connection
+    // generate a unique ID through connection_id + random_id, which is convenient for histogram data storage.
+    // we need random_id becase socketfd would be multiplexed in the same pid,
+    // but the metrics data(histogram) is MAP data, which can only be read by user-space with interval, so it would cause data delay.
+    __u64 random_id;
+    // connect operation start nanosecond
+    __u64 start_time;
+    // connect operation finish nanosecond
+    __u64 end_time;
+    // current process id
+    __u32 pid;
+    // current socket fd
+    __u32 sockfd;
+    // create from function name
+    __u8 func_name;
+
+    // the type of role in current connection
+    __u8 role;
+    // socket type
+    __u8 socket_family;
+    // is connect success or not
+    __u8 success;
+    __u32 __pad0;
+
+    // upstream
+    __u32 remote_addr_v4;
+    __u8 remote_addr_v6[16];
+    __u32 remote_port;
+    // downstream
+    __u32 local_addr_v4;
+    __u8 local_addr_v6[16];
+    __u32 local_port;
+
+    __u32 conntrack_upstream_port;
+    __u64 conntrack_upstream_iph;
+    __u64 conntrack_upstream_ipl;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} socket_connection_event_queue SEC(".maps");
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, __u32);
+    __type(value, struct socket_connect_event_t);
+    __uint(max_entries, 1);
+} socket_connect_event_per_cpu_map SEC(".maps");
+static __inline struct socket_connect_event_t* create_socket_connect_event() {
+  __u32 kZero = 0;
+  return bpf_map_lookup_elem(&socket_connect_event_per_cpu_map, &kZero);
+}
+
+// active connection cached into the hashmap
+// if connection closed, then deleted
+struct active_connection_t {
+    // random value in one active connection
+    // generate a unique ID through connection_id + random_id, which is convenient for histogram data storage
+    __u64 random_id;
+    // process id
+    __u32 pid;
+    // socket fd under process
+    __u32 sockfd;
+    // the type of role in current connection
+    __u32 role;
+    // socket type
+    __u32 socket_family;
+
+    // for protocol analyze
+    __u8 protocol;
+    // current connection is ssl
+    __u8 ssl;
+    // skip data upload when the protocol break(such as HTTP2)
+    __u8 skip_data_upload;
+    __u8 pad0;
+    __u32 pad1;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct active_connection_t);
+} active_connection_map SEC(".maps");
+static __inline __u64 gen_tgid_fd(__u32 tgid, __u32 sockfd) {
+    return ((__u64)tgid << 32) | sockfd;
+}
+struct socket_close_event_t {
+    // current connection id
+    __u64 conid;
+    // random value in one active connection
+    // generate a unique ID through connection_id + random_id, which is convenient for histogram data storage
+    __u64 random_id;
+
+    // close event execute time
+    __u64 start_time;
+    __u64 end_time;
+    // process id
+    __u32 pid;
+    // socket fd under process
+    __u32 sockfd;
+    // close success
+    __u32 success;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} socket_close_event_queue SEC(".maps");
+
+static __inline bool family_should_trace(const __u32 family) {
+    return family != AF_UNKNOWN && family != AF_INET && family != AF_INET6 ? false : true;
+}
+
+static __always_inline void submit_new_connection(void* ctx, bool success, __u32 func_name, __u32 tgid, __u32 fd, __u64 start_nacs,
+                                            struct sockaddr* addr, const struct socket* socket, struct connect_track_remote* conntrack, __u8 role) {
+    // send to the user-space the connection event
+    __u64 curr_nacs = bpf_ktime_get_ns();
+    struct socket_connect_event_t *event = create_socket_connect_event();
+    if (event == NULL) {
+        return;
+    }
+
+    __u64 conid = gen_tgid_fd(tgid, fd);
+    __u64 random_id = bpf_get_prandom_u32();
+    event->conid = conid;
+    event->random_id = random_id;
+    event->start_time = start_nacs;
+    event->end_time = curr_nacs;
+    event->func_name = func_name;
+    if (func_name == SOCKET_OPTS_TYPE_CONNECT) {
+        event->role = CONNECTION_ROLE_TYPE_CLIENT;
+    } else if (func_name == SOCKET_OPTS_TYPE_ACCEPT) {
+        event->role = CONNECTION_ROLE_TYPE_SERVER;
+    } else {
+        event->role = role;
+    }
+    event->pid = tgid;
+    event->sockfd = fd;
+
+    // cleanup and fill the conntrack
+    event->conntrack_upstream_iph = 0;
+    event->conntrack_upstream_ipl = 0;
+    event->conntrack_upstream_port = 0;
+    if (conntrack != NULL) {
+        event->conntrack_upstream_iph = conntrack->iph;
+        event->conntrack_upstream_ipl = conntrack->ipl;
+        event->conntrack_upstream_port = conntrack->port;
+    }
+    event->success = success;
+
+    __u16 port;
+    if (socket != NULL) {
+        // only get from accept function(server side)
+        struct sock* s;
+        BPF_CORE_READ_INTO(&s, socket, sk);
+
+        short unsigned int skc_family;
+        BPF_CORE_READ_INTO(&skc_family, s, __sk_common.skc_family);
+        event->socket_family = skc_family;
+
+        if (event->socket_family == AF_INET) {
+            BPF_CORE_READ_INTO(&port, s, __sk_common.skc_num);
+            event->local_port = port;
+            BPF_CORE_READ_INTO(&event->local_addr_v4, s, __sk_common.skc_rcv_saddr);
+            BPF_CORE_READ_INTO(&port, s, __sk_common.skc_dport);
+            event->remote_port = bpf_ntohs(port);
+            BPF_CORE_READ_INTO(&event->remote_addr_v4, s, __sk_common.skc_daddr);
+        } else if (event->socket_family == AF_INET6) {
+            BPF_CORE_READ_INTO(&port, s, __sk_common.skc_num);
+            event->local_port = port;
+            BPF_CORE_READ_INTO(&event->local_addr_v6, s, __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8);
+            BPF_CORE_READ_INTO(&port, s, __sk_common.skc_dport);
+            event->remote_port = bpf_ntohs(port);
+            BPF_CORE_READ_INTO(&event->remote_addr_v6, s, __sk_common.skc_v6_daddr.in6_u.u6_addr8);
+        }
+    } else if (addr != NULL) {
+        event->socket_family = _(addr->sa_family);
+        if (event->socket_family == AF_INET) {
+            struct sockaddr_in *daddr = (struct sockaddr_in *)addr;
+            bpf_probe_read(&event->remote_addr_v4, sizeof(event->remote_addr_v4), &daddr->sin_addr.s_addr);
+            bpf_probe_read(&port, sizeof(port), &daddr->sin_port);
+            event->remote_port = bpf_ntohs(port);
+        } else if (event->socket_family == AF_INET6) {
+            struct sockaddr_in6 *daddr = (struct sockaddr_in6 *)addr;
+            bpf_probe_read(&event->remote_addr_v6, sizeof(event->remote_addr_v6), &daddr->sin6_addr.s6_addr);
+            bpf_probe_read(&port, sizeof(port), &daddr->sin6_port);
+            event->remote_port = bpf_ntohs(port);
+        }
+    } else {
+        event->socket_family = AF_UNKNOWN;
+    }
+
+    bpf_perf_event_output(ctx, &socket_connection_event_queue, BPF_F_CURRENT_CPU, event, sizeof(*event));
+    if (success == false) {
+        return;
+    }
+
+    // if connect success, then add the activate connection into the kernel
+    // active connection save
+    struct active_connection_t con = {};
+    con.random_id = event->random_id;
+    con.pid = tgid;
+    con.sockfd = fd;
+    con.role = event->role;
+    con.socket_family = event->socket_family;
+    bpf_map_update_elem(&active_connection_map, &conid, &con, 0);
+}
+
+static __inline struct active_connection_t* get_or_create_active_conn(void *ctx, __u32 tgid, __u32 fd, __u32 func_name, __u8 role) {
+    __u64 conid = gen_tgid_fd(tgid, fd);
+    struct active_connection_t *conn = bpf_map_lookup_elem(&active_connection_map, &conid);
+    if (conn != NULL) {
+        return conn;
+    }
+    submit_new_connection(ctx, true, func_name, tgid, fd, 0, NULL, NULL, NULL, role);
+    return bpf_map_lookup_elem(&active_connection_map, &conid);
+}
+
+
+static __inline void submit_connection_when_not_exists(void *ctx, __u64 id, struct connect_args_t* connect_args, __u32 func_name, __u8 role) {
+    __u32 tgid = (__u32)(id >> 32);
+    __u32 fd = connect_args->fd;
+
+    __u64 conid = gen_tgid_fd(tgid, fd);
+    struct active_connection_t *conn = bpf_map_lookup_elem(&active_connection_map, &conid);
+    if (conn != NULL) {
+       return;
+    }
+    submit_new_connection(ctx, true, func_name, tgid, connect_args->fd, connect_args->start_nacs, connect_args->addr, NULL, &connect_args->remote, role);
+}
+
+static __inline void notify_close_connection(void* ctx, __u64 conid, struct active_connection_t* con, __u64 start_time, __u64 end_time, int ret) {
+    struct socket_close_event_t close_event = {};
+
+    close_event.conid = conid;
+    close_event.random_id = con->random_id;
+    close_event.start_time = start_time;
+    close_event.end_time = end_time;
+    close_event.pid = con->pid;
+    close_event.sockfd = con->sockfd;
+    close_event.success = ret > 0 ? true : false;
+
+    bpf_perf_event_output(ctx, &socket_close_event_queue, BPF_F_CURRENT_CPU, &close_event, sizeof(close_event));
+}
+
+static __inline void submit_close_connection(void* ctx, __u32 tgid, __u32 fd, __u64 start_nacs, int ret) {
+    __u64 curr_nacs = bpf_ktime_get_ns();
+    __u64 conid = gen_tgid_fd(tgid, fd);
+    struct active_connection_t* con = bpf_map_lookup_elem(&active_connection_map, &conid);
+    if (con == NULL) {
+        return;
+    }
+    notify_close_connection(ctx, conid, con, start_nacs, curr_nacs, ret);
+    bpf_map_delete_elem(&active_connection_map, &conid);
+}
\ No newline at end of file
diff --git a/bpf/accesslog/common/data_args.h b/bpf/accesslog/common/data_args.h
new file mode 100644
index 0000000..2d76062
--- /dev/null
+++ b/bpf/accesslog/common/data_args.h
@@ -0,0 +1,110 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "socket_opts.h"
+
+struct connect_track_remote {
+    __u64 iph;
+    __u64 ipl;
+    __u16 port;
+};
+
+struct sock_data_args_t {
+    __u32 fd;
+    // current read/write is calls on the sockets.
+    __u32 is_sock_event;
+    size_t iovlen;
+    unsigned int* msg_len;
+    __u64 start_nacs;
+    // buffer
+    char* buf;
+    struct iovec *iovec;
+    __u64 data_id;
+    // for openssl
+    __u32 excepted_size;
+    __u32 ifindex;
+    __u64 total_package_size;
+    __u8 package_count;
+    __u8 retransmit_package_count;
+    __u8 ssl_buffer_force_unfinished;
+    __u8 sk_role;
+    __u32 l2_enter_queue_count;
+    struct sk_buff *buffer;
+    __u64 enter_l4_time;
+    __u64 exit_l4_time;
+    __u64 l3_duration;
+    __u64 l3_rcv_duration;
+    __u64 l3_local_duration;
+    __u64 l3_output_duration;
+    __u32 total_resolve_mac_count;
+    __u32 total_net_filter_count;
+    __u64 total_resolve_mac_time;
+    __u64 total_net_filter_time;
+    __u64 total_package_to_queue_time;
+    __u64 total_package_receive_from_queue_time;
+
+    __u64 l2_duration;
+    __u64 l2_enter_queue_package_count;
+    __u64 l2_ready_send_duration;
+    __u64 l2_send_duration;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct sock_data_args_t);
+} socket_data_args SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, __u64);
+} socket_data_id_generate_map SEC(".maps");
+
+static __inline __u64 get_socket_data_id(__u8 from, __u64 id, __u32 fd) {
+    __u32 tgid = (__u32)(id >> 32);
+    __u64 key = ((__u64)tgid << 32) | fd;
+    __u64 *data_id = bpf_map_lookup_elem(&socket_data_id_generate_map, &key);
+    if (!data_id) {
+        return 0;
+    }
+    return *data_id;
+}
+
+static __inline __u64 generate_socket_data_id(__u64 id, __u32 fd, __u32 func_name, bool check) {
+    __u32 tgid = (__u32)(id >> 32);
+    __u64 key = ((__u64)tgid << 32) | fd;
+    if (check) {
+        if (tgid_should_trace(tgid) == false) {
+            return 0;
+        }
+    }
+    __u64 *data_id = bpf_map_lookup_elem(&socket_data_id_generate_map, &key);
+    if (!data_id) {
+        __u64 tmp = 0;
+        bpf_map_update_elem(&socket_data_id_generate_map, &key, &tmp, BPF_NOEXIST);
+        data_id = bpf_map_lookup_elem(&socket_data_id_generate_map, &key);
+        if (!data_id) {
+            return 0;
+        }
+    }
+    (*data_id)++;
+    return *data_id;
+}
\ No newline at end of file
diff --git a/bpf/profiling/continuous/skb.h b/bpf/accesslog/common/sock.h
similarity index 56%
copy from bpf/profiling/continuous/skb.h
copy to bpf/accesslog/common/sock.h
index ed1a9ed..d0a84ec 100644
--- a/bpf/profiling/continuous/skb.h
+++ b/bpf/accesslog/common/sock.h
@@ -15,28 +15,22 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct iovec {
-	void *iov_base;
-	__u64 iov_len;
-} __attribute__((preserve_access_index));
+#pragma once
+#include "api.h"
+#include "socket.h"
+#include "socket_opts.h"
 
-struct iov_iter {
-	__u64 count;
-	union {
-		const struct iovec *iov;
-		const struct kvec *kvec;
-		const struct bio_vec *bvec;
-		struct xarray *xarray;
-		struct pipe_inode_info *pipe;
-	};
-} __attribute__((preserve_access_index));
+static __always_inline __u8 get_sock_role(__u8 current_role, struct sock* sock) {
+    if (current_role != CONNECTION_ROLE_TYPE_UNKNOWN) {
+        return current_role;
+    }
+    // the max_ack_backlog holds the limit for the accept queue
+    // if it is a server, it will not be 0
+    int max_ack_backlog = 0;
+    if (0 != bpf_core_read(&max_ack_backlog, sizeof(max_ack_backlog),
+                &sock->sk_max_ack_backlog)) {
+    return CONNECTION_ROLE_TYPE_UNKNOWN;
+    }
 
-struct msghdr {
-	struct iov_iter	msg_iter;	/* data */
-	unsigned int	msg_flags;
-} __attribute__((preserve_access_index));
-
-struct sock {
-	struct socket		*sk_socket;
-	__u32			sk_max_ack_backlog;
-} __attribute__((preserve_access_index));
\ No newline at end of file
+    return max_ack_backlog == 0 ? CONNECTION_ROLE_TYPE_CLIENT : CONNECTION_ROLE_TYPE_SERVER;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/l24/l24.h b/bpf/accesslog/l24/l24.h
new file mode 100644
index 0000000..9ce716d
--- /dev/null
+++ b/bpf/accesslog/l24/l24.h
@@ -0,0 +1,139 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "api.h"
+#include "socket.h"
+#include "socket_opts.h"
+
+struct skb_receive_detail {
+    __u64 netif_receive_time;
+    __u64 enter_ip_rcv_time;
+    __u64 exit_ip_rcv_time;
+    __u64 ip_rcv_finish_time;
+    __u64 ip_local_time;
+    __u64 ip_local_finish_time;
+    __u64 enter_tcp_rcv_time;
+    __u64 exit_tcp_rcv_time;
+    __u64 enter_nf_time;
+    __u32 ifindex;
+    __u32 total_nf_count;
+    __u64 total_nf_time;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, struct sk_buff *);
+	__type(value, struct skb_receive_detail);
+} sk_buff_receive_detail_map SEC(".maps");
+
+struct skb_transmit_detail {
+    // l3
+    __u64 l3_enter_time;
+    __u64 l3_exit_time;
+    __u64 l3_local_time;
+    __u64 l3_output_time;
+    __u64 l3_finish_time;
+    __u16 total_nf_count;
+    __u16 total_resolve_neigh_count;
+    __u32 ifindex;
+    __u64 enter_nf_time;
+    __u64 enter_resolve_neigh_time;
+    __u64 total_nf_time;
+    __u64 total_resolve_neigh_time;
+
+    // l2
+    __u64 l2_enter_time;
+    __u64 l2_exit_time;
+    __u64 l2_start_xmit_time;
+    __u64 l2_finish_xmit_time;
+    // for loss package, for now, we only support first 4 locations, it could be changes to map-in-map
+    __u64 loss_package_location1;
+    __u64 loss_package_location2;
+    __u64 loss_package_location3;
+    __u64 loss_package_location4;
+    __u16 loss_package_count1;
+    __u16 loss_package_count2;
+    __u16 loss_package_count3;
+    __u16 loss_package_count4;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, struct sk_buff *);
+	__type(value, struct skb_transmit_detail);
+} sk_buff_transmit_detail_map SEC(".maps");
+
+#define L24_TEMP_ARGS_TRANSMIT_NF_HOOK_SLOW 1
+#define L24_TEMP_ARGS_NEIGHT_RESOLVE_OUTPUT 2
+#define L24_TEMP_ARGS_DEV_QUEUE_EMIT 3
+#define L24_TEMP_ARGS_IP_RCV 4
+#define L24_TEMP_ARGS_TCP_RCV 5
+#define L24_TEMP_ARGS_RCV_NF_HOOK_SLOW 1
+
+struct l24_tmp_args_key {
+    __u64 id;
+    __u64 type;
+};
+struct l24_tmp_args_value {
+    struct skb_transmit_detail *detail;
+    __u64 start_time;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, struct l24_tmp_args_key);
+	__type(value, struct sk_buff *);
+} sk_temp_args_map SEC(".maps");
+
+static __always_inline void save_l24_tmp_args(__u64 tpe, struct sk_buff *skb) {
+    struct l24_tmp_args_key key = {
+        .id = bpf_get_current_pid_tgid(),
+        .type = tpe,
+    };
+    bpf_map_update_elem(&sk_temp_args_map, &key, &skb, BPF_ANY);
+}
+
+static __always_inline struct skb_transmit_detail* get_l24_transmit_tmp_args(__u64 tpe) {
+    struct l24_tmp_args_key key = {
+        .id = bpf_get_current_pid_tgid(),
+        .type = tpe,
+    };
+    struct sk_buff* buff = bpf_map_lookup_elem(&sk_temp_args_map, &key);
+    if (buff == NULL) {
+        return NULL;
+    }
+    bpf_map_delete_elem(&sk_temp_args_map, &key);
+    return bpf_map_lookup_elem(&sk_buff_transmit_detail_map, buff);
+}
+
+static __always_inline struct skb_receive_detail* get_l24_rcv_tmp_args(__u64 tpe) {
+    struct l24_tmp_args_key key = {
+        .id = bpf_get_current_pid_tgid(),
+        .type = tpe,
+    };
+    struct sk_buff* buff = bpf_map_lookup_elem(&sk_temp_args_map, &key);
+    if (buff == NULL) {
+        return NULL;
+    }
+    bpf_map_delete_elem(&sk_temp_args_map, &key);
+    return bpf_map_lookup_elem(&sk_buff_receive_detail_map, buff);
+}
\ No newline at end of file
diff --git a/bpf/accesslog/l24/nf.c b/bpf/accesslog/l24/nf.c
new file mode 100644
index 0000000..1e855cd
--- /dev/null
+++ b/bpf/accesslog/l24/nf.c
@@ -0,0 +1,54 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "l24.h"
+
+SEC("kprobe/nf_hook_slow")
+int nf_hook_slow(struct pt_regs * ctx) {
+    struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_transmit_detail *transmit_detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+	if (transmit_detail != NULL) {
+	    transmit_detail->enter_nf_time = bpf_ktime_get_ns();
+	    save_l24_tmp_args(L24_TEMP_ARGS_TRANSMIT_NF_HOOK_SLOW, skb);
+	    return 0;
+	}
+	struct skb_receive_detail *recv_detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+	if (recv_detail != NULL) {
+        recv_detail->enter_nf_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_RCV_NF_HOOK_SLOW, skb);
+        return 0;
+    }
+	return 0;
+}
+
+SEC("kretprobe/nf_hook_slow")
+int nf_hook_slow_ret(struct pt_regs * ctx) {
+    struct skb_transmit_detail *transmit_detail = get_l24_transmit_tmp_args(L24_TEMP_ARGS_TRANSMIT_NF_HOOK_SLOW);
+    if (transmit_detail != NULL) {
+        transmit_detail->total_nf_count++;
+        transmit_detail->total_nf_time = bpf_ktime_get_ns() - transmit_detail->enter_nf_time;
+        return 0;
+    }
+    struct skb_receive_detail* rcv_detail = get_l24_rcv_tmp_args(L24_TEMP_ARGS_RCV_NF_HOOK_SLOW);
+    if (rcv_detail != NULL) {
+        rcv_detail->total_nf_count++;
+        rcv_detail->total_nf_time = bpf_ktime_get_ns() - rcv_detail->enter_nf_time;
+        return 0;
+    }
+	return 0;
+}
\ No newline at end of file
diff --git a/pkg/boot/register.go b/bpf/accesslog/l24/read_l2.c
similarity index 56%
copy from pkg/boot/register.go
copy to bpf/accesslog/l24/read_l2.c
index 8f0d64d..0896eeb 100644
--- a/pkg/boot/register.go
+++ b/bpf/accesslog/l24/read_l2.c
@@ -15,20 +15,26 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package boot
+#include "l24.h"
+#include "../common/data_args.h"
 
-import (
-	"github.com/apache/skywalking-rover/pkg/core"
-	"github.com/apache/skywalking-rover/pkg/logger"
-	"github.com/apache/skywalking-rover/pkg/module"
-	"github.com/apache/skywalking-rover/pkg/process"
-	"github.com/apache/skywalking-rover/pkg/profiling"
-)
+struct netif_receive_skb {
+	unsigned long long pad;
+	void * skbaddr;
+};
 
-func init() {
-	// register all active module
-	module.Register(logger.NewModule())
-	module.Register(core.NewModule())
-	module.Register(process.NewModule())
-	module.Register(profiling.NewModule())
+SEC("tracepoint/net/netif_receive_skb")
+int tracepoint_netif_receive_skb(struct netif_receive_skb *ctx) {
+    struct sk_buff * skb = (struct sk_buff *)ctx->skbaddr;
+
+    struct net_device *device = _(skb->dev);
+    int ifindex;
+    bpf_probe_read(&ifindex, sizeof(ifindex), &device->ifindex);
+
+    struct skb_receive_detail detail = {
+        .ifindex = ifindex,
+        .netif_receive_time = bpf_ktime_get_ns(),
+    };
+    bpf_map_update_elem(&sk_buff_receive_detail_map, &skb, &detail, 0);
+    return 0;
 }
diff --git a/bpf/accesslog/l24/read_l3.c b/bpf/accesslog/l24/read_l3.c
new file mode 100644
index 0000000..9779344
--- /dev/null
+++ b/bpf/accesslog/l24/read_l3.c
@@ -0,0 +1,176 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "l24.h"
+#include "../common/data_args.h"
+#include "list.h"
+
+SEC("kprobe/ip_rcv")
+int ip_rcv(struct pt_regs * ctx) {
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->enter_ip_rcv_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_IP_RCV, skb);
+    }
+    return 0;
+}
+
+SEC("kretprobe/ip_rcv")
+int ip_rcv_ret(struct pt_regs * ctx) {
+    struct skb_receive_detail* detail = get_l24_rcv_tmp_args(L24_TEMP_ARGS_IP_RCV);
+    if (detail != NULL) {
+        detail->exit_ip_rcv_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct bpf_list_head);
+} ip_list_rcv_args_map SEC(".maps");
+
+#define ip_list_foreach_skb(loc, time)                                      \
+    list_for_each_entry_data(skb, next, head, list) {                       \
+        detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);    \
+        if (detail != NULL) {                                               \
+            detail->loc = time;                                             \
+            skb_list = append_bpf_list_head(&skb_list, skb);                 \
+        }                                                                   \
+    };
+
+#define bpf_list_foreach_skb(loc, time)                                      \
+    bpf_list_for_each_foreach(skb, head) {                                   \
+        detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);     \
+        if (detail != NULL) {                                                \
+            detail->loc = time;                                              \
+        }                                                                    \
+    };
+
+SEC("kprobe/ip_list_rcv")
+int ip_list_rcv(struct pt_regs * ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct list_head *head = (struct list_head *)PT_REGS_PARM1(ctx);
+    if (head == NULL) {
+        return 0;
+    }
+    __u64 enter_rcv_time = bpf_ktime_get_ns();
+    struct skb_receive_detail *detail = NULL;
+
+    struct sk_buff *skb = NULL, *next = NULL;
+    struct bpf_list_head skb_list = init_bpf_list_head();
+    list_for_each_entry_init()
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+    ip_list_foreach_skb(enter_ip_rcv_time, enter_rcv_time)
+
+
+    bpf_map_update_elem(&ip_list_rcv_args_map, &id, &skb_list, BPF_ANY);
+    return 0;
+}
+
+SEC("kretprobe/ip_list_rcv")
+int ip_list_rcv_ret(struct pt_regs * ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct bpf_list_head *head = bpf_map_lookup_elem(&ip_list_rcv_args_map, &id);
+    if (head == NULL) {
+        return 0;
+    }
+
+    struct sk_buff *skb = NULL;
+    bpf_list_for_each_init()
+    struct skb_receive_detail *detail = NULL;
+    __u64 exit_rcv_time = bpf_ktime_get_ns();
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+    bpf_list_foreach_skb(exit_ip_rcv_time, exit_rcv_time)
+
+    bpf_map_delete_elem(&ip_list_rcv_args_map, &id);
+    return 0;
+}
+
+SEC("kprobe/ip_rcv_finish")
+int ip_rcv_finish(struct pt_regs * ctx){
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->ip_rcv_finish_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("kprobe/ip_sublist_rcv_finish")
+int ip_sublist_rcv_finish(struct pt_regs * ctx) {
+    struct list_head *head = (struct list_head *)PT_REGS_PARM1(ctx);
+    if (head == NULL) {
+        return 0;
+    }
+    __u64 rcv_finish_time = bpf_ktime_get_ns();
+    struct skb_receive_detail *detail = NULL;
+
+    struct sk_buff *skb = NULL, *next = NULL;
+    struct bpf_list_head skb_list = init_bpf_list_head();
+    list_for_each_entry_init()
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+    ip_list_foreach_skb(ip_rcv_finish_time, rcv_finish_time)
+
+    return 0;
+}
+
+SEC("kprobe/ip_local_deliver")
+int ip_local_deliver(struct pt_regs * ctx){
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->ip_local_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("kprobe/ip_local_deliver_finish")
+int ip_local_deliver_finish(struct pt_regs * ctx){
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM3(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->ip_local_finish_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
diff --git a/bpf/accesslog/l24/read_l4.c b/bpf/accesslog/l24/read_l4.c
new file mode 100644
index 0000000..5a46d72
--- /dev/null
+++ b/bpf/accesslog/l24/read_l4.c
@@ -0,0 +1,59 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "l24.h"
+#include "../common/data_args.h"
+
+SEC("kprobe/tcp_v4_rcv")
+int tcp_v4_rcv(struct pt_regs * ctx) {
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->enter_tcp_rcv_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_TCP_RCV, skb);
+    }
+    return 0;
+}
+
+SEC("kretprobe/tcp_v4_rcv")
+int tcp_v4_rcv_ret(struct pt_regs * ctx) {
+    struct skb_receive_detail* detail = get_l24_rcv_tmp_args(L24_TEMP_ARGS_TCP_RCV);
+    if (detail != NULL) {
+        detail->exit_tcp_rcv_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("kprobe/tcp_v6_rcv")
+int tcp_v6_rcv(struct pt_regs * ctx) {
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+	struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &skb);
+    if (detail != NULL) {
+        detail->enter_tcp_rcv_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_TCP_RCV, skb);
+    }
+    return 0;
+}
+
+SEC("kretprobe/tcp_v6_rcv")
+int tcp_v6_rcv_ret(struct pt_regs * ctx) {
+    struct skb_receive_detail* detail = get_l24_rcv_tmp_args(L24_TEMP_ARGS_TCP_RCV);
+    if (detail != NULL) {
+        detail->exit_tcp_rcv_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
diff --git a/bpf/accesslog/l24/write_l2.c b/bpf/accesslog/l24/write_l2.c
new file mode 100644
index 0000000..2f477df
--- /dev/null
+++ b/bpf/accesslog/l24/write_l2.c
@@ -0,0 +1,72 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "l24.h"
+#include "../common/data_args.h"
+
+struct net_dev_start_xmit_args {
+  unsigned long pad0;
+  unsigned long pad1;
+
+  void *skb;
+};
+
+struct net_dev_xmit_args {
+  unsigned long pad0;
+
+  void *skb;
+};
+
+SEC("kprobe/__dev_queue_xmit")
+int dev_queue_emit(struct pt_regs * ctx){
+    struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
+    struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->l2_enter_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_DEV_QUEUE_EMIT, skb);
+    }
+    return 0;
+}
+
+SEC("kretprobe/__dev_queue_xmit")
+int dev_queue_emit_ret(struct pt_regs * ctx){
+    struct skb_transmit_detail *detail = get_l24_transmit_tmp_args(L24_TEMP_ARGS_DEV_QUEUE_EMIT);
+    if (detail != NULL) {
+        detail->l2_exit_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("tracepoint/net/net_dev_start_xmit")
+int tracepoint_net_dev_start_xmit(struct net_dev_start_xmit_args *args) {
+    struct sk_buff * skb = args->skb;
+    struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->l2_start_xmit_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("tracepoint/net/net_dev_xmit")
+int tracepoint_net_dev_xmit(struct net_dev_xmit_args *args) {
+    struct sk_buff * skb = args->skb;
+    struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->l2_finish_xmit_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/l24/write_l3.c b/bpf/accesslog/l24/write_l3.c
new file mode 100644
index 0000000..57ba28a
--- /dev/null
+++ b/bpf/accesslog/l24/write_l3.c
@@ -0,0 +1,147 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "l24.h"
+#include "../common/data_args.h"
+
+SEC("kprobe/__ip_queue_xmit")
+int ip_queue_xmit(struct pt_regs * ctx){
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM2(ctx);
+        // update current transmit skb
+        data_args->buffer = skb;
+
+        // adding skb detail into map(for getting all l2-3 detail from skb)
+        struct skb_transmit_detail detail = {};
+        detail.l3_enter_time = bpf_ktime_get_ns();
+        bpf_map_update_elem(&sk_buff_transmit_detail_map, &skb, &detail, 0);
+    }
+    return 0;
+}
+
+SEC("kretprobe/__ip_queue_xmit")
+int ip_queue_xmit_ret(struct pt_regs * ctx){
+    __u64 id = bpf_get_current_pid_tgid();
+    // getting skb
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+	if (data_args == NULL) {
+	    return 0;
+	}
+	// getting all l2-3 detail
+	struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &data_args->buffer);
+	if (detail == NULL) {
+	    return 0;
+	}
+
+    data_args->l3_duration += bpf_ktime_get_ns() - detail->l3_enter_time;
+    if (detail->l3_output_time > 0 && detail->l3_local_time > 0) {
+        data_args->l3_local_duration += detail->l3_output_time - detail->l3_local_time;
+    }
+    if (detail->l3_finish_time > 0 && detail->l3_output_time > 0) {
+        data_args->l3_output_duration += detail->l3_finish_time - detail->l3_output_time;
+    }
+    data_args->total_resolve_mac_count = detail->total_resolve_neigh_count;
+    data_args->total_resolve_mac_time = detail->total_resolve_neigh_time;
+    data_args->total_net_filter_count = detail->total_nf_count;
+    data_args->total_net_filter_time = detail->total_nf_time;
+
+    if (detail->l2_enter_time > 0 && detail->l2_exit_time > 0) {
+        data_args->l2_duration = detail->l2_exit_time - detail->l2_enter_time;
+        data_args->l2_enter_queue_count++;
+    }
+    data_args->ifindex = _(detail->ifindex);
+    if (detail->l2_enter_time > 0) {
+        data_args->l2_enter_queue_package_count++;
+    }
+    if (detail->l2_start_xmit_time > 0 && detail->l2_enter_time > 0) {
+        data_args->l2_ready_send_duration += detail->l2_start_xmit_time - detail->l2_enter_time;
+    }
+    if (detail->l2_finish_xmit_time > 0 && detail->l2_start_xmit_time > 0) {
+        data_args->l2_send_duration += detail->l2_finish_xmit_time - detail->l2_start_xmit_time;
+    }
+    return 0;
+}
+
+SEC("kprobe/ip_local_out")
+int ip_local(struct pt_regs * ctx){
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM3(ctx);
+	struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->l3_local_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct sk_buff *);
+} ip_output_temp SEC(".maps");
+
+
+SEC("kprobe/ip_output")
+int ip_output(struct pt_regs * ctx){
+	struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM3(ctx);
+	struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->l3_output_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("kprobe/ip_finish_output2")
+int ip_finish_output2(struct pt_regs * ctx){
+    struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM3(ctx);
+	struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        long unsigned int _skb_refdst;
+        bpf_probe_read(&_skb_refdst, sizeof(_skb_refdst), &skb->_skb_refdst);
+        struct dst_entry *entry = (void *)(_skb_refdst & SKB_DST_PTRMASK);
+        struct net_device *device;
+        bpf_probe_read(&device, sizeof(device), &entry->dev);
+
+        int ifindex;
+        bpf_probe_read(&ifindex, sizeof(ifindex), &device->ifindex);
+        detail->ifindex = ifindex;
+        detail->l3_finish_time = bpf_ktime_get_ns();
+    }
+    return 0;
+}
+
+SEC("kprobe/neigh_resolve_output")
+int neigh_resolve_output(struct pt_regs * ctx){
+    struct sk_buff * skb = (struct sk_buff *)PT_REGS_PARM2(ctx);
+    struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        detail->enter_resolve_neigh_time = bpf_ktime_get_ns();
+        save_l24_tmp_args(L24_TEMP_ARGS_NEIGHT_RESOLVE_OUTPUT, skb);
+    }
+    return 0;
+}
+
+SEC("kretprobe/neigh_resolve_output")
+int neigh_resolve_output_ret(struct pt_regs * ctx){
+    struct skb_transmit_detail *detail = get_l24_transmit_tmp_args(L24_TEMP_ARGS_NEIGHT_RESOLVE_OUTPUT);
+    if (detail != NULL) {
+        detail->total_resolve_neigh_count++;
+        detail->total_resolve_neigh_time = bpf_ktime_get_ns() - detail->enter_resolve_neigh_time;
+    }
+    return 0;
+}
diff --git a/bpf/accesslog/l24/write_l4.c b/bpf/accesslog/l24/write_l4.c
new file mode 100644
index 0000000..c38ecc6
--- /dev/null
+++ b/bpf/accesslog/l24/write_l4.c
@@ -0,0 +1,103 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "l24.h"
+#include "../common/data_args.h"
+#include "../common/sock.h"
+
+struct kfree_skb_args {
+  unsigned long pad;
+
+  void *skb;
+  void *location;
+};
+
+SEC("kprobe/tcp_sendmsg")
+int tcp_sendmsg(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        data_args->enter_l4_time = bpf_ktime_get_ns();
+
+        // getting the socket role is client or server
+        struct sock *sk = (void *)PT_REGS_PARM1(ctx);
+        data_args->sk_role = get_sock_role(data_args->sk_role, sk);
+    }
+    return 0;
+};
+
+SEC("kretprobe/tcp_sendmsg")
+int tcp_sendmsg_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        data_args->exit_l4_time = bpf_ktime_get_ns();
+    }
+    return 0;
+};
+
+SEC("kprobe/tcp_transmit_skb")
+int tcp_transmit_skb(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        struct sk_buff *skb = (void *)PT_REGS_PARM2(ctx);
+        data_args->package_count++;
+        data_args->total_package_size += _(skb->len);
+    }
+    return 0;
+};
+
+SEC("tracepoint/tcp/tcp_retransmit_skb")
+int tracepoint_tcp_retransmit_skb() {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        data_args->retransmit_package_count++;
+    }
+    return 0;
+}
+
+#define UPDATE_LOSS_PACKAGE(detail, loc, count, location) \
+    if ((detail)->loc == 0) { \
+        (detail)->loc = (__u64)(location); \
+        (detail)->count = 1; \
+        return 0; \
+    } else if ((detail)->loc == (__u64)(location)) { \
+        (detail)->count++; \
+        return 0; \
+    }
+
+SEC("tracepoint/skb/kfree_skb")
+int kfree_skb(struct kfree_skb_args *args) {
+    struct sk_buff *skb = args->skb;
+    if (skb == NULL) {
+        return 0;
+    }
+    void* location = args->location;
+    if (location == NULL) {
+        return 0;
+    }
+    struct skb_transmit_detail *detail = bpf_map_lookup_elem(&sk_buff_transmit_detail_map, &skb);
+    if (detail != NULL) {
+        UPDATE_LOSS_PACKAGE(detail, loss_package_location1, loss_package_count1, location);
+        UPDATE_LOSS_PACKAGE(detail, loss_package_location2, loss_package_count2, location);
+        UPDATE_LOSS_PACKAGE(detail, loss_package_location3, loss_package_count3, location);
+        UPDATE_LOSS_PACKAGE(detail, loss_package_location4, loss_package_count4, location);
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/pkg/tools/host/network.go b/bpf/accesslog/process/process.c
similarity index 50%
copy from pkg/tools/host/network.go
copy to bpf/accesslog/process/process.c
index 34f24de..bdd29ed 100644
--- a/pkg/tools/host/network.go
+++ b/bpf/accesslog/process/process.c
@@ -15,48 +15,35 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package host
+#include "api.h"
+#include "process.h"
 
-import (
-	"net"
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} process_execute_queue SEC(".maps");
 
-	"github.com/apache/skywalking-rover/pkg/logger"
-)
+struct process_execute_event {
+    __u32 pid;
+};
 
-var interfaces map[int]*net.Interface
-var log = logger.GetLogger("tools", "host")
+struct sched_comm_fork_ctx {
+	__u64 __pad_0;
+	char parent_comm[16];
+	__u32 parent_pid;
+	char child_comm[16];
+	__u32 child_pid;
+};
 
-func init() {
-	if err := refreshInterfaces(); err != nil {
-		panic(err)
-	}
-}
+SEC("tracepoint/sched/sched_process_fork")
+int tracepoint_sched_process_fork(struct sched_comm_fork_ctx* ctx) {
+    __u32 tgid = ctx->parent_pid;
+    // adding to the monitor
+    __u32 v = 1;
+    bpf_map_update_elem(&process_monitor_control, &tgid, &v, 0);
 
-func NetworkName(ifindex int) string {
-	i := interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	if e := refreshInterfaces(); e != nil {
-		log.Warnf("error to refresh interfaces: %v", e)
-		return ""
-	}
-	i = interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	return ""
-}
-
-func refreshInterfaces() error {
-	results, err := net.Interfaces()
-	if err != nil {
-		return err
-	}
-	tmp := make(map[int]*net.Interface)
-	for _, interf := range results {
-		tmp[interf.Index] = &interf
-	}
-	interfaces = tmp
-	return nil
-}
+    // send to the user-space to check the pid should monitor or not
+    struct process_execute_event event = {};
+    event.pid = tgid;
+    bpf_perf_event_output(ctx, &process_execute_queue, BPF_F_CURRENT_CPU, &event, sizeof(event));
+    return 0;
+}
\ No newline at end of file
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/bpf/accesslog/process/process.h
similarity index 68%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to bpf/accesslog/process/process.h
index 555705c..33c35e7 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/bpf/accesslog/process/process.h
@@ -15,11 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
+#pragma once
 
-type ParseResult int
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u32);
+	__type(value, __u32);
+} process_monitor_control SEC(".maps");
 
-const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
-)
+static __inline bool tgid_should_trace(__u32 tgid) {
+    __u32 *val = bpf_map_lookup_elem(&process_monitor_control, &tgid);
+    if (!val) {
+        return false;
+    }
+    return (*val) == 1 ? true : false;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/syscalls/close.c b/bpf/accesslog/syscalls/close.c
new file mode 100644
index 0000000..d4539c6
--- /dev/null
+++ b/bpf/accesslog/syscalls/close.c
@@ -0,0 +1,70 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "socket.h"
+#include "socket_opts.h"
+#include "../process/process.h"
+#include "../common/connection.h"
+
+struct trace_point_enter_close {
+    __u64 pad_0;
+    int __syscall_nr;
+    __u32 pad_1;
+    int fd;
+};
+struct trace_point_exit_close {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    __u64 ret;
+};
+
+static __inline void process_close_sock(void* ctx, __u64 id, struct sock_close_args_t *args, int ret) {
+    __u32 tgid = (__u32)(id >> 32);
+    if (args->fd < 0) {
+        return;
+    }
+
+    submit_close_connection(ctx, tgid, args->fd, args->start_nacs, ret);
+}
+
+SEC("tracepoint/syscalls/sys_enter_close")
+int tracepoint_enter_close(struct trace_point_enter_close *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct sock_close_args_t close_args = {};
+    close_args.fd = ctx->fd;
+    close_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&closing_args, &id, &close_args, 0);
+	return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_close")
+int tracepoint_exit_close(struct trace_point_exit_close *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_close_args_t *close_args = bpf_map_lookup_elem(&closing_args, &id);
+    if (close_args) {
+        process_close_sock(ctx, id, close_args, ctx->ret);
+    }
+
+    bpf_map_delete_elem(&closing_args, &id);
+	return 0;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/syscalls/connect.c b/bpf/accesslog/syscalls/connect.c
new file mode 100644
index 0000000..30a4a7f
--- /dev/null
+++ b/bpf/accesslog/syscalls/connect.c
@@ -0,0 +1,149 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "socket.h"
+#include "socket_opts.h"
+#include "../process/process.h"
+#include "../common/connection.h"
+
+struct trace_point_enter_connect {
+    __u64 pad_0;
+    int __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct sockaddr * uservaddr;
+};
+struct trace_point_exit_connect {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    __u64 ret;
+};
+
+struct trace_point_enter_accept {
+    __u64 pad_0;
+    int __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct sockaddr * upeer_sockaddr;
+};
+struct trace_point_exit_accept {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    long ret;
+};
+
+static __inline void process_connect(void *ctx, __u64 id, struct connect_args_t *connect_args, long ret) {
+    bool success = true;
+    if (ret < 0 && ret != -EINPROGRESS) {
+        success = false;
+    }
+    if (connect_args->fd < 0) {
+        return;
+    }
+    __u32 tgid = id >> 32;
+    struct sock *sock = connect_args->sock;
+    struct socket *s = _(sock->sk_socket);
+    submit_new_connection(ctx, success, SOCKET_OPTS_TYPE_CONNECT, tgid, connect_args->fd, connect_args->start_nacs, connect_args->addr, s, &connect_args->remote, 0);
+}
+
+static __inline void process_accept(void *ctx, __u64 id, struct accept_args_t *accept_args, long ret) {
+    int fd = (int) ret;
+    __u32 tgid = id >> 32;
+    struct socket *s = accept_args->socket;
+    submit_new_connection(ctx, true, SOCKET_OPTS_TYPE_ACCEPT, tgid, fd, accept_args->start_nacs, accept_args->addr, s, NULL, 0);
+}
+
+SEC("tracepoint/syscalls/sys_enter_connect")
+int tracepoint_enter_connect(struct trace_point_enter_connect *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct connect_args_t connect_args = {};
+    connect_args.fd = ctx->fd;
+    connect_args.addr = ctx->uservaddr;
+    connect_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+	return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_connect")
+int tracepoint_exit_connect(struct trace_point_exit_connect *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct connect_args_t *connect_args;
+
+    connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args) {
+        process_connect(ctx, id, connect_args, ctx->ret);
+    }
+
+    bpf_map_delete_elem(&conecting_args, &id);
+	return 0;
+}
+
+SEC("kprobe/tcp_connect")
+int tcp_connect(struct pt_regs *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);;
+    if (connect_args) {
+        connect_args->sock = (void *)PT_REGS_PARM1(ctx);
+    }
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_accept")
+int tracepoint_enter_accept(struct trace_point_enter_accept *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct accept_args_t accept_args = {};
+    accept_args.addr = ctx->upeer_sockaddr;
+    accept_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&accepting_args, &id, &accept_args, 0);
+	return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_accept")
+int tracepoint_exit_accept(struct trace_point_exit_accept *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct accept_args_t *accept_args = bpf_map_lookup_elem(&accepting_args, &id);
+    if (accept_args) {
+        process_accept(ctx, id, accept_args, ctx->ret);
+    }
+
+    bpf_map_delete_elem(&accepting_args, &id);
+	return 0;
+}
+
+SEC("kretprobe/sock_alloc")
+int sock_alloc_ret(struct pt_regs *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct accept_args_t *accept_sock = bpf_map_lookup_elem(&accepting_args, &id);
+    if (accept_sock) {
+        struct socket *sock = (struct socket*)PT_REGS_RC(ctx);
+        accept_sock->socket = sock;
+    }
+    return 0;
+}
+
+#include "connect_conntrack.c"
\ No newline at end of file
diff --git a/bpf/accesslog/syscalls/connect_conntrack.c b/bpf/accesslog/syscalls/connect_conntrack.c
new file mode 100644
index 0000000..483599b
--- /dev/null
+++ b/bpf/accesslog/syscalls/connect_conntrack.c
@@ -0,0 +1,117 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "connect_conntrack.h"
+#include "../common/data_args.h"
+
+static __always_inline void nf_conntrack_read_in6_addr(__u64 *addr_h, __u64 *addr_l, const struct in6_addr *in6) {
+    BPF_CORE_READ_INTO(addr_h, in6, s6_addr32[0]);
+    BPF_CORE_READ_INTO(addr_l, in6, s6_addr32[2]);
+}
+static __always_inline int nf_conntrack_tuple_to_conntrack_tuple(conntrack_tuple_t *t, const struct nf_conntrack_tuple *ct) {
+    __builtin_memset(t, 0, sizeof(conntrack_tuple_t));
+
+    switch (ct->dst.protonum) {
+        case IPPROTO_TCP:
+            t->sport = ct->src.u.tcp.port;
+            t->dport = ct->dst.u.tcp.port;
+            break;
+        case IPPROTO_UDP:
+            t->sport = ct->src.u.udp.port;
+            t->dport = ct->dst.u.udp.port;
+            break;
+        default:
+            return 0;
+    }
+
+    t->sport = bpf_ntohs(t->sport);
+    t->dport = bpf_ntohs(t->dport);
+    if (t->sport == 0 || t->dport == 0) {
+        return 0;
+    }
+
+    if (ct->src.l3num == AF_INET) {
+        t->saddr_l = ct->src.u3.ip;
+        t->daddr_l = ct->dst.u3.ip;
+
+        if (!t->saddr_l || !t->daddr_l) {
+            return 0;
+        }
+//    } else if (ct->src.l3num == AF_INET6) {
+//        nf_conntrack_read_in6_addr(&t->saddr_h, &t->saddr_l, &ct->src.u3.in6);
+//        nf_conntrack_read_in6_addr(&t->daddr_h, &t->daddr_l, &ct->dst.u3.in6);
+//
+//        if (!t->saddr_h || !t->saddr_l || !t->daddr_h || !t->daddr_l) {
+//            return 0;
+//        }
+    }
+    return 1;
+}
+
+static __always_inline int nf_conn_aware(struct pt_regs* ctx, struct nf_conn *ct) {
+    if (ct == NULL) {
+        return 0;
+    }
+    __u64 id = bpf_get_current_pid_tgid();
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (!connect_args) {
+        return 0;
+    }
+
+    __u32 status;
+    if (bpf_probe_read(&status, sizeof(status), &(ct->status)) != 0) {
+        return 0; // Invalid ct pointer
+    }
+
+    if (!(status & IPS_CONFIRMED)) {
+        return 0;
+    }
+    if (!(status & IPS_NAT_MASK)) {
+        return 0;
+    }
+
+    struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
+    if (bpf_probe_read(&tuplehash, sizeof(tuplehash), &(ct->tuplehash)) != 0) {
+        return 0; // Invalid ct pointer
+    }
+
+    struct nf_conntrack_tuple reply = tuplehash[IP_CT_DIR_REPLY].tuple;
+
+    conntrack_tuple_t reply_conn = {};
+    if (!nf_conntrack_tuple_to_conntrack_tuple(&reply_conn, &reply)) {
+        return 0;
+    }
+
+    struct connect_track_remote remote = {};
+    remote.iph = reply_conn.saddr_h;
+    remote.ipl = reply_conn.saddr_l;
+    remote.port = reply_conn.sport;
+    connect_args->remote = remote;
+    bpf_map_update_elem(&conecting_args, &id, connect_args, 0);
+
+    return 0;
+}
+
+SEC("kprobe/__nf_conntrack_hash_insert")
+int nf_conntrack_hash_insert(struct pt_regs* ctx) {
+    return nf_conn_aware(ctx, (struct nf_conn*)PT_REGS_PARM1(ctx));
+}
+
+SEC("kprobe/nf_confirm")
+int nf_confirm(struct pt_regs* ctx) {
+    return nf_conn_aware(ctx, (struct nf_conn*)PT_REGS_PARM3(ctx));
+}
diff --git a/bpf/accesslog/syscalls/connect_conntrack.h b/bpf/accesslog/syscalls/connect_conntrack.h
new file mode 100644
index 0000000..0e67b9c
--- /dev/null
+++ b/bpf/accesslog/syscalls/connect_conntrack.h
@@ -0,0 +1,99 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <linux/types.h>
+
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+
+typedef struct {
+    /* Using the type unsigned __int128 generates an error in the ebpf verifier */
+    __u64 saddr_h;
+    __u64 saddr_l;
+    __u64 daddr_h;
+    __u64 daddr_l;
+    __u16 sport;
+    __u16 dport;
+    __u32 netns;
+    // Metadata description:
+    // First bit indicates if the connection is TCP (1) or UDP (0)
+    // Second bit indicates if the connection is V6 (1) or V4 (0)
+    __u32 metadata; // This is that big because it seems that we atleast need a 32-bit aligned struct
+
+    __u32 _pad;
+} conntrack_tuple_t;
+
+
+struct nf_conntrack_man {
+	union nf_inet_addr u3;
+	union nf_conntrack_man_proto u;
+	/* Layer 3 protocol */
+	u_int16_t l3num;
+} __attribute__((preserve_access_index));
+
+
+struct nf_conntrack_tuple {
+	struct nf_conntrack_man src;
+	/* These are the parts of the tuple which are fixed. */
+    	struct {
+    		union nf_inet_addr u3;
+    		union {
+    			/* Add other protocols here. */
+    			__be16 all;
+
+    			struct {
+    				__be16 port;
+    			} tcp;
+    			struct {
+    				__be16 port;
+    			} udp;
+    			struct {
+    				u_int8_t type, code;
+    			} icmp;
+    			struct {
+    				__be16 port;
+    			} dccp;
+    			struct {
+    				__be16 port;
+    			} sctp;
+    			struct {
+    				__be16 key;
+    			} gre;
+    		} u;
+
+    		/* The protocol. */
+    		u_int8_t protonum;
+
+    		/* The direction (for tuplehash) */
+    		u_int8_t dir;
+    	} dst;
+} __attribute__((preserve_access_index));
+
+struct hlist_nulls_node {
+	struct hlist_nulls_node *next, **pprev;
+} __attribute__((preserve_access_index));
+
+struct nf_conntrack_tuple_hash {
+    struct hlist_nulls_node hnnode;
+	struct nf_conntrack_tuple tuple;
+} __attribute__((preserve_access_index));
+
+struct nf_conn {
+	__u32 timeout;
+	struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
+	long unsigned int status;
+	__u32 mark;
+} __attribute__((preserve_access_index));
diff --git a/bpf/accesslog/syscalls/transfer.c b/bpf/accesslog/syscalls/transfer.c
new file mode 100644
index 0000000..23e01da
--- /dev/null
+++ b/bpf/accesslog/syscalls/transfer.c
@@ -0,0 +1,634 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "socket_opts.h"
+#include "../process/process.h"
+#include "../common/data_args.h"
+#include "../common/sock.h"
+#include "../l24/l24.h"
+#include "transfer.h"
+
+struct trace_point_common_exit {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    __u64 ret;
+};
+struct trace_point_common_write {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    char * buf;
+    size_t count;
+};
+struct trace_point_common_writev {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct iovec * vec;
+    size_t count;
+};
+struct trace_point_common_readv {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct iovec * vec;
+    size_t count;
+};
+struct trace_point_common_sendmsg {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct user_msghdr * msg;
+};
+struct trace_point_common_sendmmsg {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct mmsghdr * mmsg;
+    unsigned int vlen;
+};
+struct trace_point_enter_sendto {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    char * buf;
+    size_t count;
+    unsigned int flags;
+    struct sockaddr * addr;
+};
+struct trace_point_enter_recvfrom {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    char * buf;
+    size_t count;
+    unsigned int flags;
+    struct sockaddr * addr;
+};
+struct trace_point_common_recvmsg {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct user_msghdr * msg;
+};
+struct trace_point_common_recvmmsg {
+    __u64 pad_0;
+    __u32 __syscall_nr;
+    __u32 pad_1;
+    int fd;
+    struct mmsghdr * mmsg;
+    unsigned int vlen;
+};
+struct trace_point_skb_copy_datagram_iovec {
+    __u64 pad_0;
+    void *skb;
+};
+
+#define BPF_PROBE_READ_VAR(value, ptr) bpf_probe_read(&value, sizeof(value), ptr)
+
+SEC("tracepoint/syscalls/sys_enter_write")
+int tracepoint_enter_write(struct trace_point_common_write *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.buf = ctx->buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_WRITE, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_write")
+int tracepoint_exit_write(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args && data_args->is_sock_event) {
+        ssize_t bytes_count = ctx->ret;
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_WRITE, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sendto")
+int tracepoint_enter_sendto(struct trace_point_enter_sendto *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    if (ctx->addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = ctx->addr;
+        connect_args.fd = ctx->fd;
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.buf = ctx->buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDTO, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_sendto")
+int tracepoint_exit_sendto(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+    // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDTO, CONNECTION_ROLE_TYPE_CLIENT);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_SENDTO, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_writev")
+int tracepoint_enter_writev(struct trace_point_common_writev *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.iovec = ctx->vec;
+    data_args.iovlen = ctx->count;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_WRITE, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_writev")
+int tracepoint_exit_writev(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args && data_args->is_sock_event) {
+        ssize_t bytes_count = ctx->ret;
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_WRITEV, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_sendmsg")
+int tracepoint_enter_sendmsg(struct trace_point_common_sendmsg *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+    struct user_msghdr* msghdr = ctx->msg;
+    if (msghdr == NULL) {
+        return 0;
+    }
+
+    struct sockaddr* addr = _(msghdr->msg_name);
+    if (addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = addr;
+        connect_args.fd = ctx->fd;
+        connect_args.start_nacs = bpf_ktime_get_ns();
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.iovec = _(msghdr->msg_iov);
+    data_args.iovlen = _(msghdr->msg_iovlen);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDMSG, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_sendmsg")
+int tracepoint_exit_sendmsg(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+     // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDMSG, CONNECTION_ROLE_TYPE_CLIENT);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_SENDMSG, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_sendmmsg")
+int tracepoint_enter_sendmmsg(struct trace_point_common_sendmmsg *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+    struct mmsghdr* mmsghdr = ctx->mmsg;
+    __u32 vlen = ctx->vlen;
+    if (mmsghdr == NULL || vlen <= 0) {
+        return 0;
+    }
+
+    struct sockaddr* addr = _(mmsghdr->msg_hdr.msg_name);
+    if (addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = addr;
+        connect_args.fd = ctx->fd;
+        connect_args.start_nacs = bpf_ktime_get_ns();
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    struct iovec *msg_iov = _(mmsghdr->msg_hdr.msg_iov);
+    data_args.iovec = msg_iov;
+    size_t msg_iovlen = _(mmsghdr->msg_hdr.msg_iovlen);
+    data_args.iovlen = msg_iovlen;
+    data_args.msg_len = (unsigned int*)(&mmsghdr->msg_hdr.msg_iovlen);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_SENDMSG, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_sendmmsg")
+int tracepoint_exit_sendmmsg(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+     // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_SENDMMSG, CONNECTION_ROLE_TYPE_CLIENT);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        __u32 bytes_count;
+        BPF_PROBE_READ_VAR(bytes_count, data_args->msg_len);
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_EGRESS, true, SOCKET_OPTS_TYPE_SENDMMSG, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_read")
+int tracepoint_enter_read(struct trace_point_common_write *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.buf = ctx->buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_READ, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_read")
+int tracepoint_exit_read(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args && data_args->is_sock_event) {
+        ssize_t bytes_count = ctx->ret;
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_READ, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_readv")
+int tracepoint_enter_readv(struct trace_point_common_readv *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.iovec = ctx->vec;
+    data_args.iovlen = ctx->count;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_READV, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_readv")
+int tracepoint_exit_readv(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args && data_args->is_sock_event) {
+        ssize_t bytes_count = ctx->ret;
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_READV, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("kprobe/recv")
+int sys_recv(struct pt_regs* ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    char* buf = (void *)SYSCALL_PARM_2(ctx);
+    struct sock_data_args_t data_args = {};
+    data_args.fd = SYSCALL_PARM_1(ctx);
+    data_args.buf = buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECV, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("kretprobe/recv")
+int sys_recv_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        ssize_t bytes_count = PT_REGS_RC(ctx);
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_RECV, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_recvfrom")
+int tracepoint_enter_recvfrom(struct trace_point_enter_recvfrom *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+
+    if (ctx->addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = ctx->addr;
+        connect_args.fd = ctx->fd;
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.buf = ctx->buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVFROM, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_recvfrom")
+int tracepoint_exit_recvfrom(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+    // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVFROM, CONNECTION_ROLE_TYPE_SERVER);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_RECVFROM, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_recvmsg")
+int tracepoint_enter_recvmsg(struct trace_point_common_recvmsg *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+    struct user_msghdr* msghdr = ctx->msg;
+    if (msghdr == NULL) {
+        return 0;
+    }
+
+    struct sockaddr* addr = _(msghdr->msg_name);
+    if (addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = addr;
+        connect_args.fd = ctx->fd;
+        connect_args.start_nacs = bpf_ktime_get_ns();
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    data_args.iovec = _(msghdr->msg_iov);
+    data_args.iovlen = _(msghdr->msg_iovlen);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVMSG, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_recvmsg")
+int tracepoint_exit_recvmsg(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+     // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVMSG, CONNECTION_ROLE_TYPE_SERVER);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_RECVMSG, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_recvmmsg")
+int tracepoint_enter_recvmmsg(struct trace_point_common_recvmmsg *ctx) {
+    uint64_t id = bpf_get_current_pid_tgid();
+    if (tgid_should_trace(id >> 32) == false) {
+        return 0;
+    }
+    struct mmsghdr* mmsghdr = ctx->mmsg;
+    __u32 vlen = ctx->vlen;
+    if (mmsghdr == NULL || vlen <= 0) {
+        return 0;
+    }
+
+    struct sockaddr* addr = _(mmsghdr->msg_hdr.msg_name);
+    if (addr != NULL) {
+        struct connect_args_t connect_args = {};
+        connect_args.addr = addr;
+        connect_args.fd = ctx->fd;
+        connect_args.start_nacs = bpf_ktime_get_ns();
+        bpf_map_update_elem(&conecting_args, &id, &connect_args, 0);
+    }
+
+    struct sock_data_args_t data_args = {};
+    data_args.fd = ctx->fd;
+    struct iovec *msg_iov = _(mmsghdr->msg_hdr.msg_iov);
+    data_args.iovec = msg_iov;
+    size_t msg_iovlen = _(mmsghdr->msg_hdr.msg_iovlen);
+    data_args.iovlen = msg_iovlen;
+    data_args.msg_len = (unsigned int*)(&mmsghdr->msg_hdr.msg_iovlen);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    data_args.data_id = generate_socket_data_id(id, data_args.fd, SOCKET_OPTS_TYPE_RECVMMSG, false);
+    bpf_map_update_elem(&socket_data_args, &id, &data_args, 0);
+    return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_recvmmsg")
+int tracepoint_exit_recvmmsg(struct trace_point_common_exit *ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    ssize_t bytes_count = ctx->ret;
+
+     // connection
+    struct connect_args_t *connect_args = bpf_map_lookup_elem(&conecting_args, &id);
+    if (connect_args && bytes_count > 0) {
+        submit_connection_when_not_exists(ctx, id, connect_args, SOCKET_OPTS_TYPE_RECVMMSG, CONNECTION_ROLE_TYPE_SERVER);
+    }
+    bpf_map_delete_elem(&conecting_args, &id);
+
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args) {
+        __u32 bytes_count;
+        BPF_PROBE_READ_VAR(bytes_count, data_args->msg_len);
+        process_write_data(ctx, id, data_args, bytes_count, SOCK_DATA_DIRECTION_INGRESS, true, SOCKET_OPTS_TYPE_RECVMMSG, false);
+    }
+
+    bpf_map_delete_elem(&socket_data_args, &id);
+    return 0;
+}
+
+SEC("tracepoint/skb/skb_copy_datagram_iovec")
+int tracepoint_skb_copy_datagram_iovec(struct trace_point_skb_copy_datagram_iovec* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args == NULL) {
+        return 0;
+    }
+
+    struct sk_buff *buff = ctx->skb;
+    struct skb_receive_detail *detail = bpf_map_lookup_elem(&sk_buff_receive_detail_map, &buff);
+    if (detail == NULL) {
+        return 0;
+    }
+    bpf_map_delete_elem(&sk_buff_receive_detail_map, &buff);
+
+    // l4
+    data_args->enter_l4_time = detail->enter_tcp_rcv_time;
+    data_args->exit_l4_time = detail->exit_tcp_rcv_time;
+
+    // l3
+    if (detail->exit_ip_rcv_time > 0 && detail->enter_ip_rcv_time > 0) {
+        data_args->l3_duration += detail->exit_ip_rcv_time - detail->enter_ip_rcv_time;
+    }
+    if (detail->ip_rcv_finish_time > 0 && detail->enter_ip_rcv_time > 0) {
+        data_args->l3_rcv_duration += detail->ip_rcv_finish_time - detail->enter_ip_rcv_time;
+    }
+    if (detail->ip_local_finish_time > 0 && detail->ip_local_time > 0) {
+        data_args->l3_local_duration += detail->ip_local_finish_time - detail->ip_local_time;
+    }
+    data_args->total_net_filter_count += detail->total_nf_count;
+    data_args->total_net_filter_time += detail->total_nf_time;
+
+    // l2
+    data_args->ifindex = detail->ifindex;
+    data_args->package_count++;
+    data_args->total_package_size += _(buff->len);
+    if (detail->netif_receive_time > 0 && detail->ip_local_time > 0) {
+        data_args->total_package_to_queue_time += detail->ip_local_time - detail->netif_receive_time;
+    }
+    if (detail->ip_local_time > 0) {
+        data_args->total_package_receive_from_queue_time += bpf_ktime_get_ns() - detail->ip_local_time;
+    }
+
+    struct sock *sock = _(buff->sk);
+    if (sock != NULL) {
+        data_args->sk_role = get_sock_role(data_args->sk_role, sock);
+    }
+
+    return 0;
+}
+
+SEC("kprobe/security_socket_sendmsg")
+int security_socket_sendmsg(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        data_args->is_sock_event = true;
+    }
+    return 0;
+}
+
+SEC("kprobe/security_socket_recvmsg")
+int security_socket_recvmsg(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *data_args = bpf_map_lookup_elem(&socket_data_args, &id);
+    if (data_args != NULL) {
+        data_args->is_sock_event = true;
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/syscalls/transfer.h b/bpf/accesslog/syscalls/transfer.h
new file mode 100644
index 0000000..2c72d51
--- /dev/null
+++ b/bpf/accesslog/syscalls/transfer.h
@@ -0,0 +1,352 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "api.h"
+#include "socket_opts.h"
+#include "socket_reader.h"
+#include "protocol_analyzer.h"
+#include "../common/connection.h"
+#include "../common/data_args.h"
+
+#define SOCKET_UPLOAD_CHUNK_LIMIT 12
+
+// openssl read or write
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, struct sock_data_args_t);
+} openssl_sock_data_args SEC(".maps");
+
+struct socket_detail_t {
+    // basic information
+    __u64 connection_id;
+    __u64 random_id;
+    __u64 data_id;
+
+    // socket data operation times
+    __u64 start_nacs;
+    __u64 end_nacs;
+
+    // l2-l4
+    __u32 l4_duration;
+    __u32 l3_duration;
+    __u32 l3_local_duration;
+    __u32 l3_output_duration;
+    __u32 l3_resolve_mac_duration;
+    __u32 l3_net_filter_duration;
+    __u32 l2_duration;
+    __u32 l2_ready_send_duration;
+    __u32 l2_send_duration;
+    __u32 l2_package_to_queue_time;
+    __u32 l3_total_recv_time;
+    __u32 ifindex;
+    __u64 l4_package_rcv_from_queue_time;
+    __u64 l4_total_package_size;
+    __u8 l2_enter_queue_count;
+    __u8 l4_package_count;
+    __u8 l4_retransmit_package_count;
+    __u8 l3_resolve_mac_count;
+    __u8 l3_net_filter_count;
+    __u8 op_func_name;
+    __u8 data_protocol;
+    __u8 ssl;
+};
+
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, __u32);
+    __type(value, struct socket_detail_t);
+    __uint(max_entries, 1);
+} socket_detail_event_per_cpu_map SEC(".maps");
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} socket_detail_data_queue SEC(".maps");
+
+struct socket_data_upload_event {
+    __u8 protocol;
+    __u8 have_reduce_after_chunk;
+    __u8 direction;
+    __u8 finished;
+    __u16 sequence;
+    __u16 data_len;
+    __u64 start_time;
+    __u64 end_time;
+    __u64 conid;
+    __u64 randomid;
+    __u64 data_id;
+    __u64 total_size;
+    char buffer[MAX_TRANSMIT_SOCKET_READ_LENGTH + 1];
+};
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, __u32);
+    __type(value, struct socket_data_upload_event);
+    __uint(max_entries, 1);
+} socket_data_upload_event_per_cpu_map SEC(".maps");
+struct {
+	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
+} socket_data_upload_event_queue SEC(".maps");
+
+struct socket_data_sequence_t {
+    __u64 data_id;
+    __u16 sequence;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_LRU_HASH);
+	__uint(max_entries, 1000);
+	__type(key, __u64);
+	__type(value, struct socket_data_sequence_t);
+} socket_data_sequence_generator SEC(".maps");
+static __inline __u16 generate_socket_sequence(__u64 conid, __u64 data_id) {
+    struct socket_data_sequence_t *seq = bpf_map_lookup_elem(&socket_data_sequence_generator, &conid);
+    if (seq == NULL) {
+        struct socket_data_sequence_t data = {};
+        data.data_id = data_id;
+        data.sequence = 0;
+        bpf_map_update_elem(&socket_data_sequence_generator, &conid, &data, BPF_NOEXIST);
+        return 0;
+    }
+    if (seq->data_id != data_id) {
+        seq->data_id = data_id;
+        seq->sequence = 0;
+    } else {
+        seq->sequence++;
+    }
+    return seq->sequence;
+}
+
+static __inline void upload_socket_detail(void *ctx, __u64 conid, struct active_connection_t *connection, __u8 func_name, struct sock_data_args_t *data_args, bool ssl, __u64 end_nacs) {
+    // only send the original socket syscall(not ssl)
+    if (ssl == true) {
+        return;
+    }
+    __u32 kZero = 0;
+    struct socket_detail_t *detail = bpf_map_lookup_elem(&socket_detail_event_per_cpu_map, &kZero);
+    if (detail == NULL) {
+        return;
+    }
+
+    detail->connection_id = conid;
+    detail->random_id = connection->random_id;
+    detail->data_id = data_args->data_id;
+
+    detail->start_nacs = data_args->start_nacs;
+    detail->end_nacs = end_nacs;
+
+    detail->l4_duration = data_args->exit_l4_time - data_args->enter_l4_time;
+    detail->l3_duration = data_args->l3_duration;
+    detail->l3_local_duration = data_args->l3_local_duration;
+    detail->l3_output_duration = data_args->l3_output_duration;
+    detail->l3_resolve_mac_duration = data_args->total_resolve_mac_time;
+    detail->l3_net_filter_duration = data_args->total_net_filter_time;
+    detail->l2_duration = data_args->l2_duration;
+    detail->l2_ready_send_duration = data_args->l2_ready_send_duration;
+    detail->l2_send_duration = data_args->l2_send_duration;
+    detail->ifindex = data_args->ifindex;
+    detail->l4_total_package_size = data_args->total_package_size;
+    detail->l4_package_count = data_args->package_count;
+    detail->l4_retransmit_package_count = data_args->retransmit_package_count;
+    detail->l3_resolve_mac_count = data_args->total_resolve_mac_count;
+    detail->l3_net_filter_count = data_args->total_net_filter_count;
+    detail->op_func_name = func_name;
+    detail->data_protocol = connection->protocol;
+    detail->ssl = connection->ssl;
+    detail->l2_package_to_queue_time = data_args->total_package_to_queue_time;
+    detail->l3_total_recv_time = data_args->l3_rcv_duration;
+    detail->l2_enter_queue_count = data_args->l2_enter_queue_count;
+    detail->l4_package_rcv_from_queue_time = data_args->total_package_receive_from_queue_time;
+
+    // loss package detail
+
+    bpf_perf_event_output(ctx, &socket_detail_data_queue, BPF_F_CURRENT_CPU, detail, sizeof(*detail));
+}
+
+static __always_inline void __upload_socket_data_with_buffer(void *ctx, __u8 index, char* buf, size_t size, __u32 is_finished, __u8 have_reduce_after_chunk, struct socket_data_upload_event *event) {
+    event->sequence = index;
+    event->data_len = size;
+    event->finished = is_finished;
+    event->have_reduce_after_chunk = have_reduce_after_chunk;
+    if (size <= 0) {
+        return;
+    }
+    asm volatile("%[size] &= 0x7ff;\n" ::[size] "+r"(size) :);
+    bpf_probe_read(&event->buffer, size & 0x7ff, buf);
+
+    bpf_perf_event_output(ctx, &socket_data_upload_event_queue, BPF_F_CURRENT_CPU, event, sizeof(*event));
+}
+
+static __always_inline void upload_socket_data_buf(void *ctx, char* buf, ssize_t size, struct socket_data_upload_event *event, __u8 force_unfinished) {
+    ssize_t already_send = 0;
+#pragma unroll
+    for (__u8 index = 0; index < SOCKET_UPLOAD_CHUNK_LIMIT; index++) {
+        // calculate bytes need to send
+        ssize_t remaining = size - already_send;
+        size_t need_send_in_chunk = 0;
+        __u8 have_reduce_after_chunk = 0;
+        if (remaining > MAX_TRANSMIT_SOCKET_READ_LENGTH) {
+            need_send_in_chunk = MAX_TRANSMIT_SOCKET_READ_LENGTH;
+            have_reduce_after_chunk = 1;
+        } else {
+            need_send_in_chunk = remaining;
+        }
+
+        __u32 is_finished = (need_send_in_chunk + already_send) >= size || index == (SOCKET_UPLOAD_CHUNK_LIMIT - 1) ? true : false;
+        __u8 sequence = index;
+        if (force_unfinished == 1 && need_send_in_chunk > 0) {
+            is_finished = 0;
+            sequence = generate_socket_sequence(event->conid, event->data_id);
+        }
+        __upload_socket_data_with_buffer(ctx, sequence, buf + already_send, need_send_in_chunk, is_finished, have_reduce_after_chunk, event);
+        already_send += need_send_in_chunk;
+
+    }
+}
+
+#define UPLOAD_PER_SOCKET_DATA_IOV() \
+if (iov_index < iovlen) {                                                   \
+    struct iovec cur_iov;                                                   \
+    bpf_probe_read(&cur_iov, sizeof(cur_iov), &iov[iov_index]);             \
+    ssize_t remaining = size - already_send;                                \
+    size_t need_send_in_chunk = remaining - cur_iov_sended;                 \
+    __u8 have_reduce_after_chunk = 0;                                       \
+    if (cur_iov_sended + need_send_in_chunk > cur_iov.iov_len) {            \
+        need_send_in_chunk = cur_iov.iov_len - cur_iov_sended;              \
+        if (need_send_in_chunk > MAX_TRANSMIT_SOCKET_READ_LENGTH) {         \
+            need_send_in_chunk = MAX_TRANSMIT_SOCKET_READ_LENGTH;           \
+            have_reduce_after_chunk = 1;                                    \
+        } else {                                                            \
+            iov_index++;                                                    \
+            cur_iov_sended = 0;                                             \
+        }                                                                   \
+    } else if (need_send_in_chunk > MAX_TRANSMIT_SOCKET_READ_LENGTH) {      \
+        need_send_in_chunk = MAX_TRANSMIT_SOCKET_READ_LENGTH;               \
+        have_reduce_after_chunk = 1;                                        \
+    }                                                                       \
+    __u32 is_finished = (need_send_in_chunk + already_send) >= size || loop_count == (SOCKET_UPLOAD_CHUNK_LIMIT - 1) ? true : false;                            \
+    __upload_socket_data_with_buffer(ctx, loop_count, cur_iov.iov_base + cur_iov_sended, need_send_in_chunk, is_finished, have_reduce_after_chunk, event);      \
+    already_send += need_send_in_chunk;                                                                                              \
+    loop_count++;                                                                                                                    \
+}
+
+static __always_inline void upload_socket_data_iov(void *ctx, struct iovec* iov, const size_t iovlen, ssize_t size, struct socket_data_upload_event *event) {
+    ssize_t already_send = 0;
+    ssize_t cur_iov_sended = 0;
+    __u8 iov_index = 0;
+    __u8 loop_count = 0;
+
+    // each count is same with SOCKET_UPLOAD_CHUNK_LIMIT
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+    UPLOAD_PER_SOCKET_DATA_IOV();
+}
+
+static __inline void upload_socket_data(void *ctx, __u64 start_time, __u64 end_time, __u64 conid, struct active_connection_t *connection, struct sock_data_args_t *args, ssize_t bytes_count, __u32 existing_msg_type, __u32 data_direction, bool ssl) {
+    // must have protocol and ssl must same(plain)
+    // if the connection data is needs to skip upload, then skip
+    if (connection->protocol == CONNECTION_PROTOCOL_UNKNOWN || connection->ssl != ssl || connection->skip_data_upload == 1) {
+        return;
+    }
+    // generate event
+    __u32 kZero = 0;
+    struct socket_data_upload_event *event = bpf_map_lookup_elem(&socket_data_upload_event_per_cpu_map, &kZero);
+    if (event == NULL) {
+        return;
+    }
+
+    // basic data
+    event->start_time = start_time;
+    event->end_time = end_time;
+    event->protocol = connection->protocol;
+    event->direction = data_direction;
+    event->conid = conid;
+    event->randomid = connection->random_id;
+    event->total_size = bytes_count;
+    event->data_id = args->data_id;
+
+    if (args->buf != NULL) {
+        upload_socket_data_buf(ctx, args->buf, bytes_count, event, args->ssl_buffer_force_unfinished);
+    } else if (args->iovec != NULL) {
+        upload_socket_data_iov(ctx, args->iovec, args->iovlen, bytes_count, event);
+    }
+}
+
+static __always_inline void process_write_data(void *ctx, __u64 id, struct sock_data_args_t *args, ssize_t bytes_count,
+                                        __u32 data_direction, const bool vecs, __u8 func_name, bool ssl) {
+    __u64 curr_nacs = bpf_ktime_get_ns();
+    __u32 tgid = (__u32)(id >> 32);
+
+    if (vecs && args->iovlen <= 0) {
+        return;
+    }
+    if (args->fd < 0) {
+        return;
+    }
+    if (bytes_count <= 0) {
+        return;
+    }
+
+    // get current connection
+    struct active_connection_t *conn = get_or_create_active_conn(ctx, tgid, args->fd, func_name, args->sk_role);
+    if (conn == NULL) {
+        return;
+    }
+    // only trace ipv4, v6, or unknown
+    if (family_should_trace(conn->socket_family) == false) {
+        return;
+    }
+    // process the ssl request if the fd not found
+    struct sock_data_args_t *ssl_data_args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
+    if (ssl_data_args != NULL && ssl_data_args->fd == 0) {
+        ssl_data_args->fd = args->fd;
+        conn->ssl = true;
+    }
+
+    // if the protocol or role is unknown in the connection and the current data content is plaintext
+    // then try to use protocol analyzer to analyze request or response and protocol type
+    __u32 msg_type = 0;
+    if ((conn->role == CONNECTION_ROLE_TYPE_UNKNOWN || conn->protocol == 0) && conn->ssl == ssl) {
+        struct socket_buffer_reader_t *buf_reader = read_socket_data(args->buf, args->iovec, bytes_count);
+        if (buf_reader != NULL) {
+            msg_type = analyze_protocol(buf_reader->buffer, buf_reader->data_len, &conn->protocol);
+            // if send request data to remote address or receive response data from remote address
+            // then, recognized current connection is client
+            if ((msg_type == CONNECTION_MESSAGE_TYPE_REQUEST && data_direction == SOCK_DATA_DIRECTION_EGRESS) ||
+                (msg_type == CONNECTION_MESSAGE_TYPE_RESPONSE && data_direction == SOCK_DATA_DIRECTION_INGRESS)) {
+                conn->role = CONNECTION_ROLE_TYPE_CLIENT;
+
+            // if send response data to remote address or receive request data from remote address
+            // then, recognized current connection is server
+            } else if ((msg_type == CONNECTION_MESSAGE_TYPE_RESPONSE && data_direction == SOCK_DATA_DIRECTION_EGRESS) ||
+                       (msg_type == CONNECTION_MESSAGE_TYPE_REQUEST && data_direction == SOCK_DATA_DIRECTION_INGRESS)) {
+                conn->role = CONNECTION_ROLE_TYPE_SERVER;
+            }
+        }
+    }
+
+    __u64 conid = gen_tgid_fd(tgid, args->fd);
+    // upload the socket detail
+    upload_socket_detail(ctx, conid, conn, func_name, args, ssl, curr_nacs);
+
+    // upload the socket data if need
+    upload_socket_data(ctx, args->start_nacs, curr_nacs, conid, conn, args, bytes_count, msg_type, data_direction, ssl);
+}
\ No newline at end of file
diff --git a/bpf/accesslog/tls/go_tls.c b/bpf/accesslog/tls/go_tls.c
new file mode 100644
index 0000000..311ec73
--- /dev/null
+++ b/bpf/accesslog/tls/go_tls.c
@@ -0,0 +1,195 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "tls.h"
+#include "go_tls.h"
+#include "goid.h"
+
+SEC("uprobe/go_tls_write")
+int go_tls_write(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    __u64 goid = get_goid(id);
+    if (goid == 0) {
+        return 0;
+    }
+
+    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+    if (symaddrs == NULL) {
+        return 0;
+    }
+
+    const void* sp = (const void*)PT_REGS_SP(ctx);
+    __u64* regs = go_regabi_regs(ctx);
+    if (regs == NULL) {
+        return 0;
+    }
+
+    struct go_tls_tgid_goid_t tgid_goid = {};
+    tgid_goid.tgid = tgid;
+    tgid_goid.goid = goid;
+
+    struct go_tls_connection_args_t data_args = {};
+    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->write_connection_loc, sp, regs);
+    assign_go_tls_arg(&data_args.buffer_ptr, sizeof(data_args.buffer_ptr), symaddrs->write_buffer_loc, sp, regs);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&go_tls_active_connection_args, &tgid_goid, &data_args, 0);
+    return 0;
+}
+
+SEC("uretprobe/go_tls_write")
+int go_tls_write_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    __u64 goid = get_goid(id);
+    if (goid == 0) {
+        return 0;
+    }
+
+    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+    if (symaddrs == NULL) {
+        return 0;
+    }
+
+    const void* sp = (const void*)PT_REGS_SP(ctx);
+    __u64* regs = go_regabi_regs(ctx);
+    if (regs == NULL) {
+        return 0;
+    }
+
+    int64_t retval0 = 0;
+    assign_go_tls_arg(&retval0, sizeof(retval0), symaddrs->write_ret0_loc, sp, regs);
+    struct go_interface retval1 = {};
+    assign_go_tls_arg(&retval1, sizeof(retval1), symaddrs->write_ret1_loc, sp, regs);
+    if (retval1.ptr != 0) {
+        return 0;
+    }
+
+    struct go_tls_tgid_goid_t tgid_goid = {};
+    tgid_goid.tgid = tgid;
+    tgid_goid.goid = goid;
+
+    struct go_tls_connection_args_t *args = bpf_map_lookup_elem(&go_tls_active_connection_args, &tgid_goid);
+    if (args) {
+        struct go_interface conn_intf = {};
+        conn_intf.type = 1;
+        conn_intf.ptr = args->connection_ptr;
+        int fd = get_fd_from_go_tls_conn(conn_intf, symaddrs);
+
+        set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_GOTLS_WRITE);
+
+        struct sock_data_args_t data_args = {};
+        data_args.fd = fd;
+        data_args.buf = args->buffer_ptr;
+        data_args.start_nacs = args->start_nacs;
+        data_args.data_id = get_socket_data_id(6, id, fd);
+
+        process_write_data(ctx, id, &data_args, retval0, SOCK_DATA_DIRECTION_EGRESS, false, SOCKET_OPTS_TYPE_GOTLS_WRITE, true);
+    }
+    bpf_map_delete_elem(&go_tls_active_connection_args, &tgid_goid);
+    return 0;
+}
+
+
+SEC("uprobe/go_tls_read")
+int go_tls_read(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    __u64 goid = get_goid(id);
+    if (goid == 0) {
+        return 0;
+    }
+
+    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+    if (symaddrs == NULL) {
+        return 0;
+    }
+
+    const void* sp = (const void*)PT_REGS_SP(ctx);
+    __u64* regs = go_regabi_regs(ctx);
+    if (regs == NULL) {
+        return 0;
+    }
+
+    struct go_tls_tgid_goid_t tgid_goid = {};
+    tgid_goid.tgid = tgid;
+    tgid_goid.goid = goid;
+
+    struct go_tls_connection_args_t data_args = {};
+    assign_go_tls_arg(&data_args.connection_ptr, sizeof(data_args.connection_ptr), symaddrs->read_connection_loc, sp, regs);
+    assign_go_tls_arg(&data_args.buffer_ptr, sizeof(data_args.buffer_ptr), symaddrs->read_buffer_loc, sp, regs);
+    data_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&go_tls_active_connection_args, &tgid_goid, &data_args, 0);
+    return 0;
+}
+
+SEC("uretprobe/go_tls_read")
+int go_tls_read_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    __u64 goid = get_goid(id);
+    if (goid == 0) {
+        return 0;
+    }
+
+    struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+    if (symaddrs == NULL) {
+        return 0;
+    }
+
+    const void* sp = (const void*)PT_REGS_SP(ctx);
+    __u64* regs = go_regabi_regs(ctx);
+    if (regs == NULL) {
+        return 0;
+    }
+
+    int64_t retval0 = 0;
+    assign_go_tls_arg(&retval0, sizeof(retval0), symaddrs->read_ret0_loc, sp, regs);
+    struct go_interface retval1 = {};
+    assign_go_tls_arg(&retval1, sizeof(retval1), symaddrs->read_ret1_loc, sp, regs);
+    if (retval1.ptr != 0) {
+        return 0;
+    }
+
+    struct go_tls_tgid_goid_t tgid_goid = {};
+    tgid_goid.tgid = tgid;
+    tgid_goid.goid = goid;
+
+    struct go_tls_connection_args_t *args = bpf_map_lookup_elem(&go_tls_active_connection_args, &tgid_goid);
+    if (args) {
+        struct go_interface conn_intf = {};
+        conn_intf.type = 1;
+        conn_intf.ptr = args->connection_ptr;
+        int fd = get_fd_from_go_tls_conn(conn_intf, symaddrs);
+
+        set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_GOTLS_READ);
+
+        struct sock_data_args_t data_args = {};
+        data_args.fd = fd;
+        data_args.buf = args->buffer_ptr;
+        data_args.start_nacs = args->start_nacs;
+        data_args.data_id = get_socket_data_id(8, id, fd);
+
+        process_write_data(ctx, id, &data_args, retval0, SOCK_DATA_DIRECTION_INGRESS, false, SOCKET_OPTS_TYPE_GOTLS_WRITE, true);
+    }
+    bpf_map_delete_elem(&go_tls_active_connection_args, &tgid_goid);
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/tls/go_tls.h b/bpf/accesslog/tls/go_tls.h
new file mode 100644
index 0000000..1057ef9
--- /dev/null
+++ b/bpf/accesslog/tls/go_tls.h
@@ -0,0 +1,49 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "symbol_offsets.h"
+
+struct go_tls_tgid_goid_t {
+    __u64 tgid;
+    __u64 goid;
+};
+struct go_tls_connection_args_t {
+    void* connection_ptr;
+    char* buffer_ptr;
+    __u64 start_nacs;
+};
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, struct go_tls_tgid_goid_t);
+	__type(value, struct go_tls_connection_args_t);
+} go_tls_active_connection_args SEC(".maps");
+
+static __always_inline int get_fd_from_go_tls_conn(struct go_interface conn, struct go_tls_args_symaddr_t* symaddr) {
+    // read connection
+    bpf_probe_read(&conn, sizeof(conn), conn.ptr + symaddr->tls_conn_offset);
+
+    if (conn.type != symaddr->tcp_conn_offset) {
+        return 0;
+    }
+
+    void* fd_ptr;
+    bpf_probe_read(&fd_ptr, sizeof(fd_ptr), conn.ptr);
+    __u64 sysfd;
+    bpf_probe_read(&sysfd, sizeof(sysfd), fd_ptr + symaddr->fd_sys_offset);
+    return sysfd;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/tls/node_tls.c b/bpf/accesslog/tls/node_tls.c
new file mode 100644
index 0000000..6f293d2
--- /dev/null
+++ b/bpf/accesslog/tls/node_tls.c
@@ -0,0 +1,50 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "node_tls.h"
+
+SEC("uprobe/node_tls_wrap")
+int node_tls_wrap(struct pt_regs* ctx) {
+    void* tls_wrap = (void*)PT_REGS_PARM1(ctx);
+    __u64 id = bpf_get_current_pid_tgid();
+    bpf_map_update_elem(&node_tls_wrap_construct_args_map, &id, &tls_wrap, 0);
+    return 0;
+}
+
+SEC("uretprobe/node_tls_wrap")
+int node_tls_wrap_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    bpf_map_delete_elem(&node_tls_wrap_construct_args_map, &id);
+    return 0;
+}
+
+SEC("uretprobe/ssl_new")
+int node_tls_ret_ssl(struct pt_regs* ctx) {
+    // get ssl data
+    void* ssl = (void*)PT_REGS_RC(ctx);
+    if (ssl == NULL) {
+        return 0;
+    }
+    // get node tls_wrap
+    __u64 id = bpf_get_current_pid_tgid();
+    struct ssl_wrap **wrap = bpf_map_lookup_elem(&node_tls_wrap_construct_args_map, &id);
+    if (wrap == NULL) {
+        return 0;
+    }
+    bpf_map_update_elem(&node_tls_ssl_wrap_mapping, &ssl, wrap, 0);
+    return 0;
+}
\ No newline at end of file
diff --git a/bpf/accesslog/tls/node_tls.h b/bpf/accesslog/tls/node_tls.h
new file mode 100644
index 0000000..b51472d
--- /dev/null
+++ b/bpf/accesslog/tls/node_tls.h
@@ -0,0 +1,79 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+struct node_tls_symaddr_t {
+    __u32 tlsWrapStreamListenerOffset;
+    __u32 streamListenerStreamOffset;
+    __u32 streamBaseStreamResourceOffset;
+    __u32 libuvStreamWrapStreamBaseOffset;
+    __u32 libuvStreamWrapStreamOffset;
+    __u32 uvStreamSIOWatcherOffset;
+    __u32 uvIOSFDOffset;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u64);
+	__type(value, void*);
+} node_tls_wrap_construct_args_map SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, void*);
+	__type(value, void*);
+} node_tls_ssl_wrap_mapping SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_HASH);
+	__uint(max_entries, 10000);
+	__type(key, __u32);
+	__type(value, struct node_tls_symaddr_t);
+} node_tls_symaddr_map SEC(".maps");
+static __inline int get_node_tls_wrap_fd(__u32 tgid, void *tlsWrap) {
+    struct node_tls_symaddr_t *addr = bpf_map_lookup_elem(&node_tls_symaddr_map, &tgid);
+    if (addr == NULL) {
+        return -1;
+    }
+
+    void *stream = NULL;
+    bpf_probe_read(&stream, sizeof(stream), tlsWrap + addr->tlsWrapStreamListenerOffset + addr->streamListenerStreamOffset);
+    if (stream == NULL) {
+        return -1;
+    }
+
+    void *uv_stream = NULL;
+    bpf_probe_read(&uv_stream, sizeof(uv_stream), stream - addr->streamBaseStreamResourceOffset - addr->libuvStreamWrapStreamBaseOffset +
+                                                          addr->libuvStreamWrapStreamOffset);
+    if (uv_stream == NULL) {
+        return -1;
+    }
+
+    __u64 fd;
+    bpf_probe_read(&fd, sizeof(fd), uv_stream + addr->uvStreamSIOWatcherOffset + addr->uvIOSFDOffset);
+    return fd;
+}
+static __inline int get_node_tls_fd(__u32 tgid, void *ssl) {
+    void **tlsWrap = bpf_map_lookup_elem(&node_tls_ssl_wrap_mapping, &ssl);
+    if (tlsWrap == NULL) {
+        return -1;
+    }
+    return get_node_tls_wrap_fd(tgid, *tlsWrap);
+}
\ No newline at end of file
diff --git a/bpf/accesslog/tls/openssl.c b/bpf/accesslog/tls/openssl.c
new file mode 100644
index 0000000..5b2c974
--- /dev/null
+++ b/bpf/accesslog/tls/openssl.c
@@ -0,0 +1,132 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "symbol_offsets.h"
+#include "openssl.h"
+#include "node_tls.h"
+
+static __inline void process_openssl_data(struct pt_regs* ctx, __u64 id, __u32 data_direction, struct sock_data_args_t* args, __u32 func_name) {
+    int bytes_count = PT_REGS_RC(ctx);
+    if (data_direction == SOCK_DATA_DIRECTION_INGRESS) {
+        // not reading finish, needs to keep reading
+        // NOTE: if the connection is server side role, and receive a unfinished message,
+        // the message type and protocol may could not be recognized.
+        // because some SSL framework only read one byte on each SSL_read method call,
+        // unless we save the buffer data, then process the SSL data.
+        size_t excepted_size = args->excepted_size;
+        if (bytes_count > 0 && bytes_count >= excepted_size) {
+            args->ssl_buffer_force_unfinished = 1;
+        }
+    }
+    process_write_data(ctx, id, args, bytes_count, data_direction, false, func_name, true);
+}
+
+static int get_fd_symaddr(__u32 tgid, bool read, void* ssl) {
+    struct openssl_symaddr* addr = get_openssl_symaddr(tgid);
+    if (addr == NULL) {
+        return -1;
+    }
+    __u32 bio_offset = read ? addr->bio_read_offset : addr->bio_write_offset;
+    __u32 fd_offset = addr->fd_offset;
+
+    void *bio = NULL;
+    bpf_probe_read(&bio, sizeof(bio), ssl + bio_offset);
+    __u32 fd;
+    bpf_probe_read(&fd, sizeof(fd), bio + fd_offset);
+
+    return fd;
+}
+
+static int get_fd(uint32_t tgid, bool read, void* ssl) {
+    int fd = 0;
+
+    fd = get_fd_symaddr(tgid, read, ssl);
+    if (fd > 2) {
+        return fd;
+    }
+
+    fd = get_node_tls_fd(tgid, ssl);
+    if (fd > 0) {
+        return fd;
+    }
+
+    return 0;
+}
+
+SEC("uprobe/ssl_write")
+int openssl_write(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    void* ssl = (void*)PT_REGS_PARM1(ctx);
+    __u32 fd = get_fd(tgid, false, ssl);
+
+    char* buf = (char*)PT_REGS_PARM2(ctx);
+    struct sock_data_args_t data_args = {};
+    data_args.fd = fd;
+    data_args.buf = buf;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&openssl_sock_data_args, &id, &data_args, 0);
+
+    set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_SSL_WRITE);
+    return 0;
+}
+
+SEC("uretprobe/ssl_write")
+int openssl_write_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
+    if (args && args->fd > 0) {
+        args->data_id = get_socket_data_id(2, id, args->fd);
+        process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_EGRESS, args, SOCKET_OPTS_TYPE_SSL_WRITE);
+    }
+    bpf_map_delete_elem(&openssl_sock_data_args, &id);
+    return 0;
+}
+
+SEC("uprobe/ssl_read")
+int openssl_read(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    __u32 tgid = id >> 32;
+
+    void* ssl = (void*)PT_REGS_PARM1(ctx);
+    __u32 fd = get_fd(tgid, true, ssl);
+
+    char* buf = (char*)PT_REGS_PARM2(ctx);
+    size_t excepted_size = PT_REGS_PARM3(ctx);
+    struct sock_data_args_t data_args = {};
+    data_args.fd = fd;
+    data_args.buf = buf;
+    data_args.excepted_size = excepted_size;
+    data_args.start_nacs = bpf_ktime_get_ns();
+    bpf_map_update_elem(&openssl_sock_data_args, &id, &data_args, 0);
+
+    set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_SSL_WRITE);
+    return 0;
+}
+
+SEC("uretprobe/ssl_read")
+int openssl_read_ret(struct pt_regs* ctx) {
+    __u64 id = bpf_get_current_pid_tgid();
+    struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
+    if (args && args->fd > 0) {
+        args->data_id = get_socket_data_id(4, id, args->fd);
+        process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_INGRESS, args, SOCKET_OPTS_TYPE_SSL_READ);
+    }
+    bpf_map_delete_elem(&openssl_sock_data_args, &id);
+    return 0;
+}
\ No newline at end of file
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/bpf/accesslog/tls/openssl.h
similarity index 88%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to bpf/accesslog/tls/openssl.h
index 555705c..3fa197d 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/bpf/accesslog/tls/openssl.h
@@ -15,11 +15,3 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
-
-type ParseResult int
-
-const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
-)
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/bpf/accesslog/tls/tls.h
similarity index 68%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to bpf/accesslog/tls/tls.h
index 555705c..52a2c34 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/bpf/accesslog/tls/tls.h
@@ -15,11 +15,15 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
+#pragma once
 
-type ParseResult int
+#include "../common/connection.h"
+#include "socket_opts.h"
 
-const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
-)
+static __always_inline void set_conn_as_ssl(struct pt_regs* ctx, __u32 tgid, __u32 fd, __u32 func_name) {
+    struct active_connection_t* conn = get_or_create_active_conn(ctx, tgid, fd, func_name, CONNECTION_ROLE_TYPE_UNKNOWN);
+    if (conn == NULL) {
+        return;
+    }
+    conn->ssl = true;
+};
diff --git a/bpf/include/list.h b/bpf/include/list.h
new file mode 100644
index 0000000..9658687
--- /dev/null
+++ b/bpf/include/list.h
@@ -0,0 +1,102 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "api.h"
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop cursor.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_head within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+    __u8 i = 0; \
+	for (pos = list_entry(_((head)->next), typeof(*pos), member),	\
+		n = list_entry(_(pos->member.next), typeof(*pos), member);	\
+	     &pos->member != (head) && i < 255;					\
+	     pos = n, n = list_entry(_(n->member.next), typeof(*n), member), i++)
+
+// use for for-each the list without for loop(lower linux kernel)
+// use list_for_each_entry_init at first, and use list_for_each_entry_data multiples for the loop
+#define list_for_each_entry_init() \
+    bool list_is_first = true; \
+    bool list_should_enter = false;
+
+#define list_for_each_entry_data(pos, n, head, member) \
+    if (list_is_first) {                                              \
+        list_should_enter = true;                                     \
+        list_is_first = false;                                        \
+        pos = list_entry(_((head)->next), typeof(*pos), member);      \
+        n = list_entry(_(pos->member.next), typeof(*pos), member);    \
+    } else if (list_should_enter) {                                   \
+        pos = n;                                                      \
+        n = list_entry(_(n->member.next), typeof(*n), member);        \
+        list_should_enter = &pos->member != (head);                   \
+    } \
+    if (list_should_enter)
+
+// Customized BPF List implementation
+struct bpf_list_head {
+    void *data;
+	struct bpf_list_head *next;
+};
+
+static inline struct bpf_list_head init_bpf_list_head() {
+    struct bpf_list_head head = {};
+    head.data = NULL;
+    head.next = NULL;
+    return head;
+}
+
+static inline struct bpf_list_head append_bpf_list_head(struct bpf_list_head* head, void *data) {
+    struct bpf_list_head new_head = init_bpf_list_head();
+    new_head.data = data;
+    new_head.next = head;
+    return new_head;
+}
+
+static inline int bpf_list_empty(struct bpf_list_head *head) {
+	return head->next == NULL;
+}
+
+#define bpf_list_for_each_init()			\
+    bool bpf_list_is_first = true;          \
+    struct bpf_list_head *current_node = NULL;
+
+#define bpf_list_for_each_foreach(pos, head)			\
+    if (bpf_list_is_first) {                                \
+        current_node = head;                            \
+        pos = head->data;\
+    } else if (current_node != NULL) {              \
+        current_node = current_node->next;                \
+        if (current_node != NULL) {\
+            pos = current_node->data; \
+        }\
+    }                       \
+    if (current_node != NULL && current_node->next != NULL)
\ No newline at end of file
diff --git a/bpf/include/protocol_analyzer.h b/bpf/include/protocol_analyzer.h
index 737e557..7efc85e 100644
--- a/bpf/include/protocol_analyzer.h
+++ b/bpf/include/protocol_analyzer.h
@@ -71,6 +71,18 @@ static __inline __u32 infer_http1_message(const char* buf, size_t count) {
     return CONNECTION_MESSAGE_TYPE_UNKNOWN;
 }
 
+static bool is_http2_magic(const char *buf_src, size_t count)
+{
+	static const char magic[] = "PRI * HTTP/2";
+	char buffer[sizeof(magic)] = { 0 };
+	bpf_probe_read(buffer, sizeof(buffer) - 1, buf_src);
+	for (int idx = 0; idx < sizeof(magic); ++idx) {
+		if (magic[idx] == buffer[idx])
+			continue;
+		return false;
+	}
+	return true;
+}
 
 // HTTP 2.x
 // frame format: https://www.rfc-editor.org/rfc/rfc7540.html#section-4.1
@@ -97,6 +109,10 @@ static __inline __u32 infer_http2_message(const char* buf, size_t count) {
     // header info
     __u8 staticInx, headerBlockFragmentOffset;
 
+    if (is_http2_magic(buf, count)) {
+        frameOffset = 24;
+    }
+
     // each all frame
 #pragma unroll
     for (__u8 i = 0; i < kFrameLoopCount; i++) {
diff --git a/bpf/profiling/network/socket.h b/bpf/include/socket.h
similarity index 83%
rename from bpf/profiling/network/socket.h
rename to bpf/include/socket.h
index ee0a294..b446bbb 100644
--- a/bpf/profiling/network/socket.h
+++ b/bpf/include/socket.h
@@ -62,9 +62,21 @@ struct socket {
 	struct sock		*sk;
 } __attribute__((preserve_access_index));
 
+struct iov_iter {
+	__u64 count;
+	union {
+		const struct iovec *iov;
+		const struct kvec *kvec;
+		const struct bio_vec *bvec;
+		struct xarray *xarray;
+		struct pipe_inode_info *pipe;
+	};
+} __attribute__((preserve_access_index));
+
 struct sock {
-	struct sock_common	__sk_common;
+    struct sock_common	__sk_common;
 	struct socket		*sk_socket;
+	__u32			sk_max_ack_backlog;
 } __attribute__((preserve_access_index));
 
 struct tcp_sock {
@@ -95,7 +107,20 @@ struct rb_node {
 	struct rb_node *rb_right;
 	struct rb_node *rb_left;
 } __attribute__((preserve_access_index));
+
 struct sk_buff {
+    union {
+        struct {
+            struct sk_buff *next;
+            struct sk_buff *prev;
+            union {
+                 struct net_device *dev;
+                 long unsigned int dev_scratch;
+            };
+        } __attribute__((preserve_access_index));
+        struct rb_node rbnode;
+        struct list_head list;
+    };
 	struct sock		*sk;
 	union {
         struct {
@@ -111,6 +136,8 @@ struct sk_buff {
     int			skb_iif;
     unsigned int len;
     unsigned int data_len;
+    unsigned char		*head,
+                        *data;
 } __attribute__((preserve_access_index));
 
 struct net {
diff --git a/bpf/include/socket_opts.h b/bpf/include/socket_opts.h
new file mode 100644
index 0000000..8aeafca
--- /dev/null
+++ b/bpf/include/socket_opts.h
@@ -0,0 +1,57 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+// the socket operation type
+#define SOCKET_OPTS_TYPE_CONNECT    1
+#define SOCKET_OPTS_TYPE_ACCEPT     2
+#define SOCKET_OPTS_TYPE_CLOSE      3
+#define SOCKET_OPTS_TYPE_SEND       4
+#define SOCKET_OPTS_TYPE_SENDTO     5
+#define SOCKET_OPTS_TYPE_SENDMSG    6
+#define SOCKET_OPTS_TYPE_SENDMMSG   7
+#define SOCKET_OPTS_TYPE_SENDFILE   8
+#define SOCKET_OPTS_TYPE_WRITE      9
+#define SOCKET_OPTS_TYPE_WRITEV     10
+#define SOCKET_OPTS_TYPE_READ       11
+#define SOCKET_OPTS_TYPE_READV      12
+#define SOCKET_OPTS_TYPE_RECV       13
+#define SOCKET_OPTS_TYPE_RECVFROM   14
+#define SOCKET_OPTS_TYPE_RECVMSG    15
+#define SOCKET_OPTS_TYPE_RECVMMSG   16
+#define SOCKET_OPTS_TYPE_RESENT     17
+#define SOCKET_OPTS_TYPE_SSL_WRITE  18
+#define SOCKET_OPTS_TYPE_SSL_READ   19
+#define SOCKET_OPTS_TYPE_GOTLS_WRITE 20
+#define SOCKET_OPTS_TYPE_GOTLS_READ  21
+
+// for protocol analyze need to read
+#define MAX_PROTOCOL_SOCKET_READ_LENGTH 31
+// for transmit to the user space
+#define MAX_TRANSMIT_SOCKET_READ_LENGTH 2047
+
+// unknown the connection type, not trigger the syscall connect,accept
+#define AF_UNKNOWN 0xff
+
+#define CONNECTION_ROLE_TYPE_UNKNOWN 0
+#define CONNECTION_ROLE_TYPE_CLIENT 1
+#define CONNECTION_ROLE_TYPE_SERVER 2
+
+// data direction
+#define SOCK_DATA_DIRECTION_INGRESS 1 //receive from
+#define SOCK_DATA_DIRECTION_EGRESS 2  //write to
diff --git a/bpf/include/socket_reader.h b/bpf/include/socket_reader.h
new file mode 100644
index 0000000..28b177d
--- /dev/null
+++ b/bpf/include/socket_reader.h
@@ -0,0 +1,64 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "socket_opts.h"
+
+struct socket_buffer_reader_t {
+    __u32 data_len;
+    char buffer[MAX_PROTOCOL_SOCKET_READ_LENGTH + 1];
+};
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, __u32);
+    __type(value, struct socket_buffer_reader_t);
+    __uint(max_entries, 1);
+} socket_buffer_reader_map SEC(".maps");
+
+static __inline struct socket_buffer_reader_t* read_socket_data(char* buf, struct iovec *iovec, __u32 bytes_count) {
+    __u64 size = 0;
+    __u32 kZero = 0;
+    char* data_buf;
+    struct socket_buffer_reader_t* reader = bpf_map_lookup_elem(&socket_buffer_reader_map, &kZero);
+    if (reader == NULL) {
+        return NULL;
+    }
+    if (buf != NULL) {
+        data_buf = buf;
+        size = bytes_count;
+    } else if (iovec != NULL) {
+        struct iovec iov;
+        bpf_probe_read(&iov, sizeof(iov), iovec);
+        __u64 tmp = iov.iov_len;
+        if (tmp > bytes_count) {
+            tmp = bytes_count;
+        }
+        data_buf = (char *)iov.iov_base;
+        size = tmp;
+    }
+    if (size <= 0) {
+        return NULL;
+    }
+    if (size > MAX_PROTOCOL_SOCKET_READ_LENGTH) {
+        size = MAX_PROTOCOL_SOCKET_READ_LENGTH;
+    }
+    asm volatile("%[size] &= 0x1f;\n" ::[size] "+r"(size) :);
+    bpf_probe_read(&reader->buffer, size & MAX_PROTOCOL_SOCKET_READ_LENGTH, data_buf);
+    reader->data_len = size & MAX_PROTOCOL_SOCKET_READ_LENGTH;
+    return reader;
+}
\ No newline at end of file
diff --git a/bpf/profiling/continuous/network.c b/bpf/profiling/continuous/network.c
index b4591aa..42aa6c5 100644
--- a/bpf/profiling/continuous/network.c
+++ b/bpf/profiling/continuous/network.c
@@ -30,6 +30,7 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_tracing.h>
 #include <bpf/bpf_core_read.h>
+#include <sys/uio.h>
 #include "network.h"
 #include "protocol_analyzer.h"
 
@@ -85,10 +86,10 @@ static __always_inline void process_data(struct pt_regs *ctx, __u64 id, void *ch
 static __always_inline void process_msghdr_data(struct pt_regs *ctx, __u64 id, void *channel_ref, struct msghdr *msg) {
     const struct iovec *iovec;
     iovec = _KERNEL(msg->msg_iter.iov);
-    struct iovec iov;
-    bpf_probe_read(&iov, sizeof(iov), iovec);
-    char* buf = (char *)iov.iov_base;
-    __u64 size = iov.iov_len;
+    struct iovec iov_data;
+    bpf_probe_read(&iov_data, sizeof(iov_data), iovec);
+    char* buf = (char *)iov_data.iov_base;
+    __u64 size = iov_data.iov_len;
 
     return process_data(ctx, id, channel_ref, buf, size, bpf_ktime_get_ns());
 }
diff --git a/bpf/profiling/continuous/network.h b/bpf/profiling/continuous/network.h
index 461b037..29735a7 100644
--- a/bpf/profiling/continuous/network.h
+++ b/bpf/profiling/continuous/network.h
@@ -16,7 +16,7 @@
 // under the License.
 
 #include "api.h"
-#include "skb.h"
+#include "socket.h"
 
 #define MAX_PROTOCOL_SOCKET_READ_LENGTH 255
 
@@ -63,4 +63,9 @@ struct {
 } socket_buffer_reader_map SEC(".maps");
 struct {
 	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
-} socket_buffer_send_queue SEC(".maps");
\ No newline at end of file
+} socket_buffer_send_queue SEC(".maps");
+
+struct msghdr {
+	struct iov_iter	msg_iter;	/* data */
+	unsigned int	msg_flags;
+} __attribute__((preserve_access_index));
\ No newline at end of file
diff --git a/bpf/profiling/network/args.h b/bpf/profiling/network/args.h
index f61b134..418edfe 100644
--- a/bpf/profiling/network/args.h
+++ b/bpf/profiling/network/args.h
@@ -17,40 +17,10 @@
 
 #include "api.h"
 #include "socket.h"
+#include "socket_opts.h"
 
 #pragma once
 
-// for protocol analyze need to read
-#define MAX_PROTOCOL_SOCKET_READ_LENGTH 31
-// for transmit to the user space
-#define MAX_TRANSMIT_SOCKET_READ_LENGTH 2047
-
-// unknown the connection type, not trigger the syscall connect,accept
-#define AF_UNKNOWN 0xff
-
-// the socket operation type
-#define SOCKET_OPTS_TYPE_CONNECT    1
-#define SOCKET_OPTS_TYPE_ACCEPT     2
-#define SOCKET_OPTS_TYPE_CLOSE      3
-#define SOCKET_OPTS_TYPE_SEND       4
-#define SOCKET_OPTS_TYPE_SENDTO     5
-#define SOCKET_OPTS_TYPE_SENDMSG    6
-#define SOCKET_OPTS_TYPE_SENDMMSG   7
-#define SOCKET_OPTS_TYPE_SENDFILE   8
-#define SOCKET_OPTS_TYPE_WRITE      9
-#define SOCKET_OPTS_TYPE_WRITEV     10
-#define SOCKET_OPTS_TYPE_READ       11
-#define SOCKET_OPTS_TYPE_READV      12
-#define SOCKET_OPTS_TYPE_RECV       13
-#define SOCKET_OPTS_TYPE_RECVFROM   14
-#define SOCKET_OPTS_TYPE_RECVMSG    15
-#define SOCKET_OPTS_TYPE_RECVMMSG   16
-#define SOCKET_OPTS_TYPE_RESENT     17
-#define SOCKET_OPTS_TYPE_SSL_WRITE  18
-#define SOCKET_OPTS_TYPE_SSL_READ   19
-#define SOCKET_OPTS_TYPE_GOTLS_WRITE 20
-#define SOCKET_OPTS_TYPE_GOTLS_READ  21
-
 struct {
 	__uint(type, BPF_MAP_TYPE_HASH);
 	__uint(max_entries, 10000);
@@ -119,10 +89,6 @@ struct {
 	__type(value, struct accept_args_t);
 } accepting_args SEC(".maps");
 
-// data direction
-#define SOCK_DATA_DIRECTION_INGRESS 1 //receive from
-#define SOCK_DATA_DIRECTION_EGRESS 2  //write to
-
 // syscall: data writing or receive
 struct sock_data_args_t {
     __u32 fd;
diff --git a/configs/rover_configs.yaml b/configs/rover_configs.yaml
index 90132d5..05859b0 100644
--- a/configs/rover_configs.yaml
+++ b/configs/rover_configs.yaml
@@ -151,4 +151,20 @@ profiling:
       # the duration of the profiling task
       execute_duration: ${ROVER_PROFILING_CONTINUOUS_TRIGGER_EXECUTE_DURATION:10m}
       # the minimal duration between the execution of the same profiling task
-      silence_duration: ${ROVER_PROFILING_CONTINUOUS_TRIGGER_SILENCE_DURATION:20m}
\ No newline at end of file
+      silence_duration: ${ROVER_PROFILING_CONTINUOUS_TRIGGER_SILENCE_DURATION:20m}
+
+access_log:
+  # Is active the access log monitoring
+  active: ${ROVER_ACCESS_LOG_ACTIVE:false}
+  flush:
+    # The max count of access log when flush to the backend
+    max_count: ${ROVER_ACCESS_LOG_FLUSH_MAX_COUNT:2000}
+    # The period of flush access log to the backend
+    period: ${ROVER_ACCESS_LOG_FLUSH_PERIOD:5s}
+  protocol_analyze:
+    # The size of socket data buffer on each CPU
+    per_cpu_buffer: ${ROVER_ACCESS_LOG_PROTOCOL_ANALYZE_PER_CPU_BUFFER:400KB}
+    # The count of parallel protocol analyzer
+    parallels: ${ROVER_ACCESS_LOG_PROTOCOL_ANALYZE_PARALLELS:2}
+    # The size of per paralleled analyzer queue
+    queue_size: ${ROVER_ACCESS_LOG_PROTOCOL_ANALYZE_QUEUE_SIZE:5000}
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 7dea1cc..94fc0b8 100644
--- a/go.mod
+++ b/go.mod
@@ -18,14 +18,14 @@ require (
 	github.com/stretchr/testify v1.8.1
 	github.com/zekroTJA/timedmap v1.4.0
 	golang.org/x/arch v0.0.0-20220722155209-00200b7164a7
-	golang.org/x/net v0.6.0
-	golang.org/x/sys v0.5.0
+	golang.org/x/net v0.17.0
+	golang.org/x/sys v0.13.0
 	google.golang.org/grpc v1.44.0
 	k8s.io/api v0.23.5
 	k8s.io/apimachinery v0.23.5
 	k8s.io/client-go v0.23.5
 	k8s.io/utils v0.0.0-20211116205334-6203023598ed
-	skywalking.apache.org/repo/goapi v0.0.0-20230301143132-aa3f8469385b
+	skywalking.apache.org/repo/goapi v0.0.0-20231225085619-53f5be6739c4
 )
 
 require (
@@ -57,12 +57,12 @@ require (
 	github.com/tklauser/numcpus v0.3.0 // indirect
 	github.com/yusufpapurcu/wmi v1.2.2 // indirect
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
-	golang.org/x/term v0.5.0 // indirect
-	golang.org/x/text v0.7.0 // indirect
+	golang.org/x/term v0.13.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
 	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
 	google.golang.org/appengine v1.6.7 // indirect
 	google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
-	google.golang.org/protobuf v1.28.1 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/ini.v1 v1.66.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index 3a3798e..f9e5af8 100644
--- a/go.sum
+++ b/go.sum
@@ -478,6 +478,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -515,6 +516,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -561,8 +563,10 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -593,6 +597,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -668,13 +673,17 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -684,8 +693,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -748,6 +759,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -901,8 +913,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -964,5 +976,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLz
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-skywalking.apache.org/repo/goapi v0.0.0-20230301143132-aa3f8469385b h1:VAWQr1mJk4P/a8VZ9UASY8H53wj0zdLHgYvhddyQcXw=
-skywalking.apache.org/repo/goapi v0.0.0-20230301143132-aa3f8469385b/go.mod h1:WovoDv1GA+8VuvHPVJL7q/fL0KlYPBZq5rTMCFQRzJU=
+skywalking.apache.org/repo/goapi v0.0.0-20231225085619-53f5be6739c4 h1:boI2sHrjhiXdidajUn1KyVNC7CvC/pwIn9zr52TuXBQ=
+skywalking.apache.org/repo/goapi v0.0.0-20231225085619-53f5be6739c4/go.mod h1:oD2dxcDAHVIt95Ee7kJHgZ5f64QNhrqTjQYARwfafc4=
diff --git a/pkg/tools/host/network.go b/pkg/accesslog/bpf/loader.go
similarity index 50%
copy from pkg/tools/host/network.go
copy to pkg/accesslog/bpf/loader.go
index 34f24de..5a4f827 100644
--- a/pkg/tools/host/network.go
+++ b/pkg/accesslog/bpf/loader.go
@@ -15,48 +15,42 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package host
+package bpf
 
 import (
-	"net"
+	"github.com/hashicorp/go-multierror"
 
-	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
 )
 
-var interfaces map[int]*net.Interface
-var log = logger.GetLogger("tools", "host")
+// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
+// nolint
+//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -no-global-types -target $TARGET -cc $BPF_CLANG -cflags $BPF_CFLAGS bpf $REPO_ROOT/bpf/accesslog/accesslog.c -- -I$REPO_ROOT/bpf/include
 
-func init() {
-	if err := refreshInterfaces(); err != nil {
-		panic(err)
-	}
+type Loader struct {
+	*btf.Linker
+	*bpfObjects
 }
 
-func NetworkName(ifindex int) string {
-	i := interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	if e := refreshInterfaces(); e != nil {
-		log.Warnf("error to refresh interfaces: %v", e)
-		return ""
+func NewLoader() (*Loader, error) {
+	objs := bpfObjects{}
+	if err := loadBpfObjects(&objs, btf.GetEBPFCollectionOptionsIfNeed()); err != nil {
+		return nil, err
 	}
-	i = interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	return ""
+
+	return &Loader{
+		bpfObjects: &objs,
+		Linker:     btf.NewLinker(),
+	}, nil
 }
 
-func refreshInterfaces() error {
-	results, err := net.Interfaces()
-	if err != nil {
-		return err
+func (l *Loader) Close() error {
+	var err error
+	if e := l.bpfObjects.Close(); e != nil {
+		err = multierror.Append(err, e)
 	}
-	tmp := make(map[int]*net.Interface)
-	for _, interf := range results {
-		tmp[interf.Index] = &interf
+	if e := l.Linker.Close(); e != nil {
+		err = multierror.Append(err, e)
 	}
-	interfaces = tmp
-	return nil
+	return err
 }
diff --git a/pkg/accesslog/collector/close.go b/pkg/accesslog/collector/close.go
new file mode 100644
index 0000000..27bfbec
--- /dev/null
+++ b/pkg/accesslog/collector/close.go
@@ -0,0 +1,56 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/module"
+)
+
+var closeLog = logger.GetLogger("access_log", "collector", "close")
+
+var closeCollectorInstance = NewCloseCollector()
+
+type CloseCollector struct {
+}
+
+func NewCloseCollector() *CloseCollector {
+	return &CloseCollector{}
+}
+
+func (c *CloseCollector) Start(_ *module.Manager, context *common.AccessLogContext) error {
+	context.BPF.AddTracePoint("syscalls", "sys_enter_close", context.BPF.TracepointEnterClose)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_close", context.BPF.TracepointExitClose)
+
+	context.BPF.ReadEventAsync(context.BPF.SocketCloseEventQueue, func(data interface{}) {
+		event := data.(*events.SocketCloseEvent)
+		closeLog.Debugf("receive close event, connection ID: %d, randomID: %d, pid: %d, fd: %d",
+			event.ConnectionID, event.RandomID, event.PID, event.SocketFD)
+		wapperedEvent := context.ConnectionMgr.OnConnectionClose(event)
+		forwarder.SendCloseEvent(context, wapperedEvent)
+	}, func() interface{} {
+		return &events.SocketCloseEvent{}
+	})
+	return nil
+}
+
+func (c *CloseCollector) Stop() {
+}
diff --git a/bpf/profiling/continuous/skb.h b/pkg/accesslog/collector/collector.go
similarity index 59%
rename from bpf/profiling/continuous/skb.h
rename to pkg/accesslog/collector/collector.go
index ed1a9ed..e7d6e9b 100644
--- a/bpf/profiling/continuous/skb.h
+++ b/pkg/accesslog/collector/collector.go
@@ -15,28 +15,25 @@
 // specific language governing permissions and limitations
 // under the License.
 
-struct iovec {
-	void *iov_base;
-	__u64 iov_len;
-} __attribute__((preserve_access_index));
+package collector
 
-struct iov_iter {
-	__u64 count;
-	union {
-		const struct iovec *iov;
-		const struct kvec *kvec;
-		const struct bio_vec *bvec;
-		struct xarray *xarray;
-		struct pipe_inode_info *pipe;
-	};
-} __attribute__((preserve_access_index));
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/module"
+)
 
-struct msghdr {
-	struct iov_iter	msg_iter;	/* data */
-	unsigned int	msg_flags;
-} __attribute__((preserve_access_index));
+type Collector interface {
+	Start(mgr *module.Manager, context *common.AccessLogContext) error
+	Stop()
+}
 
-struct sock {
-	struct socket		*sk_socket;
-	__u32			sk_max_ack_backlog;
-} __attribute__((preserve_access_index));
\ No newline at end of file
+func Collectors() []Collector {
+	return []Collector{
+		l24CollectorsInstance,
+		transferCollectInstance,
+		closeCollectorInstance,
+		connectCollectInstance,
+		tlsCollectInstance,
+		processCollectInstance,
+	}
+}
diff --git a/pkg/accesslog/collector/connect.go b/pkg/accesslog/collector/connect.go
new file mode 100644
index 0000000..a93a215
--- /dev/null
+++ b/pkg/accesslog/collector/connect.go
@@ -0,0 +1,162 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+	"encoding/binary"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/module"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/ip"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/link"
+
+	"golang.org/x/sys/unix"
+)
+
+var connectLogger = logger.GetLogger("access_log", "collector", "connect")
+
+var connectCollectInstance = NewConnectCollector()
+
+type ConnectCollector struct {
+}
+
+func NewConnectCollector() *ConnectCollector {
+	return &ConnectCollector{}
+}
+
+func (c *ConnectCollector) Start(_ *module.Manager, context *common.AccessLogContext) error {
+	context.BPF.AddTracePoint("syscalls", "sys_enter_connect", context.BPF.TracepointEnterConnect)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_connect", context.BPF.TracepointExitConnect)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_accept", context.BPF.TracepointEnterAccept)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_accept", context.BPF.TracepointExitAccept)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_accept4", context.BPF.TracepointEnterAccept)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_accept4", context.BPF.TracepointExitAccept)
+
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{
+		"tcp_connect": context.BPF.TcpConnect,
+	})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{
+		"sock_alloc": context.BPF.SockAllocRet,
+	})
+
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{
+		"__nf_conntrack_hash_insert": context.BPF.NfConntrackHashInsert,
+		"nf_confirm":                 context.BPF.NfConfirm,
+	})
+
+	context.BPF.ReadEventAsync(context.BPF.SocketConnectionEventQueue, func(data interface{}) {
+		event := data.(*events.SocketConnectEvent)
+		connectLogger.Debugf("receive connect event, connection ID: %d, randomID: %d, pid: %d, fd: %d, role: %s: func: %s, family: %d, success: %d",
+			event.ConID, event.RandomID, event.PID, event.SocketFD, enums.ConnectionRole(event.Role), enums.SocketFunctionName(event.FuncName),
+			event.SocketFamily, event.ConnectSuccess)
+		socketPair := buildSocketFromConnectEvent(event)
+		if socketPair == nil {
+			connectLogger.Debugf("cannot found the socket paire from connect event, connection ID: %d, randomID: %d",
+				event.ConID, event.RandomID)
+			return
+		}
+		context.ConnectionMgr.OnConnectEvent(event, socketPair)
+		forwarder.SendConnectEvent(context, event, socketPair)
+	}, func() interface{} {
+		return &events.SocketConnectEvent{}
+	})
+
+	return nil
+}
+
+func (c *ConnectCollector) Stop() {
+}
+
+func buildSocketFromConnectEvent(event *events.SocketConnectEvent) *ip.SocketPair {
+	if event.SocketFamily != unix.AF_INET && event.SocketFamily != unix.AF_INET6 && event.SocketFamily != enums.SocketFamilyUnknown {
+		// if not ipv4, ipv6 or unknown, ignore
+		return nil
+	}
+	socketPair := buildSocketPair(event)
+	if socketPair != nil && socketPair.IsValid() {
+		return socketPair
+	}
+	// if only the local port not success, maybe the upstream port is not open, so it could be continued
+	if isOnlyLocalPortEmpty(socketPair) {
+		event.ConnectSuccess = 0
+		return socketPair
+	}
+
+	pair, err := ip.ParseSocket(event.PID, event.SocketFD)
+	if err != nil {
+		connectLogger.Warnf("cannot found the socket, pid: %d, socket FD: %d", event.PID, event.SocketFD)
+		return nil
+	}
+	pair.Role = enums.ConnectionRole(event.Role)
+	return pair
+}
+
+func isOnlyLocalPortEmpty(socketPair *ip.SocketPair) bool {
+	if socketPair == nil {
+		return false
+	}
+	port := socketPair.SrcPort
+	defer func() {
+		socketPair.SrcPort = port
+	}()
+	socketPair.SrcPort = 1
+	return socketPair.IsValid()
+}
+
+func buildSocketPair(event *events.SocketConnectEvent) *ip.SocketPair {
+	var result *ip.SocketPair
+	if event.SocketFamily == unix.AF_INET {
+		result = &ip.SocketPair{
+			Family:  uint32(event.SocketFamily),
+			Role:    enums.ConnectionRoleClient,
+			SrcIP:   ip.ParseIPV4(event.LocalAddrV4),
+			SrcPort: uint16(event.LocalAddrPort),
+		}
+		if event.ConnTrackUpstreamIPl != 0 && event.ConnTrackUpstreamPort != 0 {
+			result.DestIP = ip.ParseIPV4(uint32(event.ConnTrackUpstreamIPl))
+			result.DestPort = uint16(event.ConnTrackUpstreamPort)
+		} else {
+			result.DestIP = ip.ParseIPV4(event.RemoteAddrV4)
+			result.DestPort = uint16(event.RemoteAddrPort)
+		}
+	} else if event.SocketFamily == unix.AF_INET6 {
+		result = &ip.SocketPair{
+			Family:  uint32(event.SocketFamily),
+			Role:    enums.ConnectionRoleClient,
+			SrcIP:   ip.ParseIPV6(event.LocalAddrV6),
+			SrcPort: uint16(event.LocalAddrPort),
+		}
+		if event.ConnTrackUpstreamIPl != 0 && event.ConnTrackUpstreamPort != 0 {
+			var ipv6 [16]uint8
+			binary.BigEndian.PutUint64(ipv6[0:8], event.ConnTrackUpstreamIPh)
+			binary.BigEndian.PutUint64(ipv6[8:16], event.ConnTrackUpstreamIPl)
+			result.DestIP = ip.ParseIPV6(ipv6)
+			result.DestPort = uint16(event.ConnTrackUpstreamPort)
+		} else {
+			result.DestIP = ip.ParseIPV6(event.RemoteAddrV6)
+			result.DestPort = uint16(event.RemoteAddrPort)
+		}
+	}
+	return result
+}
diff --git a/pkg/accesslog/collector/l24.go b/pkg/accesslog/collector/l24.go
new file mode 100644
index 0000000..109617a
--- /dev/null
+++ b/pkg/accesslog/collector/l24.go
@@ -0,0 +1,93 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/module"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/link"
+)
+
+var l24CollectorsInstance = NewL24Collector()
+
+type L24Collector struct {
+}
+
+func NewL24Collector() *L24Collector {
+	return &L24Collector{}
+}
+
+func (c *L24Collector) Start(mgr *module.Manager, context *common.AccessLogContext) error {
+	c.startWrite(mgr, context)
+	c.startRead(mgr, context)
+	return nil
+}
+
+func (c *L24Collector) startRead(_ *module.Manager, context *common.AccessLogContext) {
+	// l2
+	context.BPF.AddTracePoint("net", "netif_receive_skb", context.BPF.TracepointNetifReceiveSkb)
+
+	// l3
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_list_rcv": context.BPF.IpListRcv})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"ip_list_rcv": context.BPF.IpListRcvRet})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_rcv": context.BPF.IpRcv})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"ip_rcv": context.BPF.IpRcvRet})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_rcv_finish": context.BPF.IpRcvFinish})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_sublist_rcv_finish": context.BPF.IpSublistRcvFinish})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_local_deliver": context.BPF.IpLocalDeliver})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_local_deliver_finish": context.BPF.IpLocalDeliverFinish})
+
+	// l4
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"tcp_v4_rcv": context.BPF.TcpV4Rcv})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"tcp_v4_rcv": context.BPF.TcpV4RcvRet})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"tcp_v6_rcv": context.BPF.TcpV6Rcv})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"tcp_v6_rcv": context.BPF.TcpV6RcvRet})
+}
+
+func (c *L24Collector) startWrite(_ *module.Manager, context *common.AccessLogContext) {
+	// l4
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"tcp_sendmsg": context.BPF.TcpSendmsg})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"tcp_sendmsg": context.BPF.TcpSendmsgRet})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"__tcp_transmit_skb": context.BPF.TcpTransmitSkb})
+	context.BPF.AddTracePoint("tcp", "tcp_retransmit_skb", context.BPF.TracepointTcpRetransmitSkb)
+	context.BPF.AddTracePoint("skb", "kfree_skb", context.BPF.KfreeSkb)
+
+	// l3
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"__ip_queue_xmit": context.BPF.IpQueueXmit})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"__ip_queue_xmit": context.BPF.IpQueueXmitRet})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"__ip_local_out": context.BPF.IpLocal})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_output": context.BPF.IpOutput})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"ip_finish_output2": context.BPF.IpFinishOutput2})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"neigh_resolve_output": context.BPF.NeighResolveOutput})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"neigh_resolve_output": context.BPF.NeighResolveOutputRet})
+
+	// netlink
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"nf_hook_slow": context.BPF.NfHookSlow})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"nf_hook_slow": context.BPF.NfHookSlowRet})
+
+	// l2
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"__dev_queue_xmit": context.BPF.DevQueueEmit})
+	context.BPF.AddLink(link.Kretprobe, map[string]*ebpf.Program{"__dev_queue_xmit": context.BPF.DevQueueEmitRet})
+	context.BPF.AddTracePoint("net", "net_dev_start_xmit", context.BPF.TracepointNetDevStartXmit)
+	context.BPF.AddTracePoint("net", "net_dev_xmit", context.BPF.TracepointNetDevXmit)
+}
+
+func (c *L24Collector) Stop() {
+}
diff --git a/pkg/boot/register.go b/pkg/accesslog/collector/process.go
similarity index 50%
copy from pkg/boot/register.go
copy to pkg/accesslog/collector/process.go
index 8f0d64d..e4dbdce 100644
--- a/pkg/boot/register.go
+++ b/pkg/accesslog/collector/process.go
@@ -15,20 +15,39 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package boot
+package collector
 
 import (
-	"github.com/apache/skywalking-rover/pkg/core"
-	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
 	"github.com/apache/skywalking-rover/pkg/module"
-	"github.com/apache/skywalking-rover/pkg/process"
-	"github.com/apache/skywalking-rover/pkg/profiling"
 )
 
-func init() {
-	// register all active module
-	module.Register(logger.NewModule())
-	module.Register(core.NewModule())
-	module.Register(process.NewModule())
-	module.Register(profiling.NewModule())
+var processCollectInstance = NewProcessCollector()
+
+// ProcessCollector Management all processes which needs to be monitored
+type ProcessCollector struct {
+}
+
+func NewProcessCollector() *ProcessCollector {
+	return &ProcessCollector{}
+}
+
+func (p *ProcessCollector) Start(_ *module.Manager, context *common.AccessLogContext) error {
+	// monitor process been execute
+	context.BPF.AddTracePoint("sched", "sched_process_fork", context.BPF.TracepointSchedProcessFork)
+
+	context.BPF.ReadEventAsync(context.BPF.ProcessExecuteQueue, func(data interface{}) {
+		context.ConnectionMgr.OnNewProcessExecuting(int32(data.(*ProcessExecuteEvent).PID))
+	}, func() interface{} {
+		return &ProcessExecuteEvent{}
+	})
+
+	return nil
+}
+
+func (p *ProcessCollector) Stop() {
+}
+
+type ProcessExecuteEvent struct {
+	PID uint32
 }
diff --git a/pkg/accesslog/collector/protocols/http1.go b/pkg/accesslog/collector/protocols/http1.go
new file mode 100644
index 0000000..e25b5c1
--- /dev/null
+++ b/pkg/accesslog/collector/protocols/http1.go
@@ -0,0 +1,234 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package protocols
+
+import (
+	"container/list"
+	"io"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+var http1Log = logger.GetLogger("accesslog", "collector", "protocols", "http1")
+
+func init() {
+	registeredProtocols[enums.ConnectionProtocolHTTP] = func(ctx *common.AccessLogContext) Protocol {
+		return &HTTP1Protocol{ctx: ctx}
+	}
+}
+
+type HTTP1Protocol struct {
+	ctx *common.AccessLogContext
+}
+
+type HTTP1Metrics struct {
+	halfRequests *list.List
+}
+
+func (p *HTTP1Protocol) GenerateConnection(connectionID uint64) ProtocolMetrics {
+	return &HTTP1Metrics{
+		halfRequests: list.New(),
+	}
+}
+
+func (p *HTTP1Protocol) Analyze(metrics ProtocolMetrics, buf *buffer.Buffer, _ *AnalyzeHelper) error {
+	buf.ResetForLoopReading()
+	for {
+		if !buf.PrepareForReading() {
+			return nil
+		}
+
+		messageType, err := reader.IdentityMessageType(buf)
+		if err != nil {
+			http1Log.Debugf("failed to identity message type, %v", err)
+			if buf.SkipCurrentElement() {
+				break
+			}
+			continue
+		}
+
+		var result enums.ParseResult
+		switch messageType {
+		case reader.MessageTypeRequest:
+			result, _ = p.handleRequest(metrics, buf)
+		case reader.MessageTypeResponse:
+			result, _ = p.handleResponse(metrics, buf)
+		case reader.MessageTypeUnknown:
+			result = enums.ParseResultSkipPackage
+		}
+
+		finishReading := false
+		switch result {
+		case enums.ParseResultSuccess:
+			finishReading = buf.RemoveReadElements()
+		case enums.ParseResultSkipPackage:
+			finishReading = buf.SkipCurrentElement()
+		}
+
+		if finishReading {
+			break
+		}
+	}
+	return nil
+}
+
+func (p *HTTP1Protocol) handleRequest(metrics ProtocolMetrics, buf *buffer.Buffer) (enums.ParseResult, error) {
+	req, result, err := reader.ReadRequest(buf, true)
+	if err != nil {
+		return enums.ParseResultSkipPackage, err
+	}
+	if result != enums.ParseResultSuccess {
+		return result, nil
+	}
+	metrics.(*HTTP1Metrics).appendRequestToList(req)
+	return result, nil
+}
+
+func (p *HTTP1Protocol) handleResponse(metrics ProtocolMetrics, b *buffer.Buffer) (enums.ParseResult, error) {
+	http1Metrics := metrics.(*HTTP1Metrics)
+	firstRequest := http1Metrics.halfRequests.Front()
+	if firstRequest == nil {
+		return enums.ParseResultSkipPackage, nil
+	}
+	request := http1Metrics.halfRequests.Remove(firstRequest).(*reader.Request)
+
+	// parsing response
+	response, result, err := reader.ReadResponse(request, b, true)
+	defer func() {
+		// if parsing response failed, then put the request back to the list
+		if result != enums.ParseResultSuccess {
+			http1Metrics.halfRequests.PushFront(request)
+		}
+	}()
+	if err != nil {
+		return enums.ParseResultSkipPackage, err
+	} else if result != enums.ParseResultSuccess {
+		return result, nil
+	}
+
+	// getting the request and response, then send to the forwarder
+	p.handleHTTPData(request, response)
+	return enums.ParseResultSuccess, nil
+}
+
+func (p *HTTP1Protocol) handleHTTPData(request *reader.Request, response *reader.Response) {
+	detailEvents := make([]*events.SocketDetailEvent, 0)
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, request.HeaderBuffer())
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, request.BodyBuffer())
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, response.HeaderBuffer())
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, response.BodyBuffer())
+
+	if len(detailEvents) == 0 {
+		http1Log.Warnf("cannot found any detail events for HTTP/1.x protocol, data id: %d-%d",
+			request.MinDataID(), response.BodyBuffer().LastSocketBuffer().DataID())
+		return
+	}
+	originalRequest := request.Original()
+	originalResponse := response.Original()
+
+	defer func() {
+		p.closeStream(originalRequest.Body)
+		p.closeStream(originalResponse.Body)
+	}()
+	forwarder.SendTransferProtocolEvent(p.ctx, detailEvents, &v3.AccessLogProtocolLogs{
+		Protocol: &v3.AccessLogProtocolLogs_Http{
+			Http: &v3.AccessLogHTTPProtocol{
+				StartTime: forwarder.BuildOffsetTimestamp(detailEvents[0].StartTime),
+				EndTime:   forwarder.BuildOffsetTimestamp(detailEvents[len(detailEvents)-1].EndTime),
+				Version:   v3.AccessLogHTTPProtocolVersion_HTTP1,
+				Request: &v3.AccessLogHTTPProtocolRequest{
+					Method:             transformHTTPMethod(originalRequest.Method),
+					Path:               originalRequest.URL.Path,
+					SizeOfHeadersBytes: uint64(request.HeaderBuffer().DataSize()),
+					SizeOfBodyBytes:    uint64(request.BodyBuffer().DataSize()),
+
+					Trace: analyzeTraceInfo(func(key string) string {
+						return originalRequest.Header.Get(key)
+					}, http1Log),
+				},
+				Response: &v3.AccessLogHTTPProtocolResponse{
+					StatusCode:         int32(originalResponse.StatusCode),
+					SizeOfHeadersBytes: uint64(response.HeaderBuffer().DataSize()),
+					SizeOfBodyBytes:    uint64(response.BodyBuffer().DataSize()),
+				},
+			},
+		},
+	})
+}
+
+func (p *HTTP1Protocol) closeStream(ioReader io.Closer) {
+	if ioReader != nil {
+		_ = ioReader.Close()
+	}
+}
+
+func transformHTTPMethod(method string) v3.AccessLogHTTPProtocolRequestMethod {
+	switch method {
+	case "GET":
+		return v3.AccessLogHTTPProtocolRequestMethod_Get
+	case "POST":
+		return v3.AccessLogHTTPProtocolRequestMethod_Post
+	case "PUT":
+		return v3.AccessLogHTTPProtocolRequestMethod_Put
+	case "DELETE":
+		return v3.AccessLogHTTPProtocolRequestMethod_Delete
+	case "HEAD":
+		return v3.AccessLogHTTPProtocolRequestMethod_Head
+	case "OPTIONS":
+		return v3.AccessLogHTTPProtocolRequestMethod_Options
+	case "TRACE":
+		return v3.AccessLogHTTPProtocolRequestMethod_Trace
+	case "CONNECT":
+		return v3.AccessLogHTTPProtocolRequestMethod_Connect
+	case "PATCH":
+		return v3.AccessLogHTTPProtocolRequestMethod_Patch
+	}
+	http1Log.Warnf("unknown http method: %s", method)
+	return v3.AccessLogHTTPProtocolRequestMethod_Get
+}
+
+func (m *HTTP1Metrics) appendRequestToList(req *reader.Request) {
+	if m.halfRequests.Len() == 0 {
+		m.halfRequests.PushFront(req)
+		return
+	}
+	if m.halfRequests.Back().Value.(*reader.Request).MinDataID() < req.MinDataID() {
+		m.halfRequests.PushBack(req)
+		return
+	}
+	beenAdded := false
+	for element := m.halfRequests.Front(); element != nil; element = element.Next() {
+		existEvent := element.Value.(*reader.Request)
+		if existEvent.MinDataID() > req.MinDataID() {
+			m.halfRequests.InsertBefore(req, element)
+			beenAdded = true
+			break
+		}
+	}
+	if !beenAdded {
+		m.halfRequests.PushBack(req)
+	}
+}
diff --git a/pkg/accesslog/collector/protocols/http2.go b/pkg/accesslog/collector/protocols/http2.go
new file mode 100644
index 0000000..f9a2e3d
--- /dev/null
+++ b/pkg/accesslog/collector/protocols/http2.go
@@ -0,0 +1,314 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package protocols
+
+import (
+	"errors"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/host"
+
+	"golang.org/x/net/http2"
+	"golang.org/x/net/http2/hpack"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+// maxHTTP2StreamingTime is the max time of an HTTP/2 streaming, if the streaming is too long, then this streaming will split
+var maxHTTP2StreamingTime = time.Minute * 3
+
+var http2Log = logger.GetLogger("accesslog", "collector", "protocols", "http2")
+
+func init() {
+	registeredProtocols[enums.ConnectionProtocolHTTP2] = func(ctx *common.AccessLogContext) Protocol {
+		return &HTTP2Protocol{ctx: ctx}
+	}
+}
+
+type HTTP2Protocol struct {
+	ctx *common.AccessLogContext
+}
+
+type HTTP2Metrics struct {
+	connectionID uint64
+	hpackDecoder *hpack.Decoder
+
+	streams map[uint32]*HTTP2Streaming
+}
+
+type HTTP2Streaming struct {
+	reqHeader        map[string]string
+	respHeader       map[string]string
+	reqHeaderBuffer  *buffer.Buffer
+	reqBodyBuffer    *buffer.Buffer
+	isInResponse     bool
+	status           int
+	respHeaderBuffer *buffer.Buffer
+	respBodyBuffer   *buffer.Buffer
+}
+
+func (r *HTTP2Protocol) GenerateConnection(connectionID uint64) ProtocolMetrics {
+	return &HTTP2Metrics{
+		connectionID: connectionID,
+		hpackDecoder: hpack.NewDecoder(4096, nil),
+		streams:      make(map[uint32]*HTTP2Streaming),
+	}
+}
+
+func (r *HTTP2Protocol) Analyze(metrics ProtocolMetrics, buf *buffer.Buffer, helper *AnalyzeHelper) error {
+	http2Log.Debugf("ready to analyze HTTP/2 protocol data, connection ID: %d", metrics.(*HTTP2Metrics).connectionID)
+	http2Metrics := metrics.(*HTTP2Metrics)
+	buf.ResetForLoopReading()
+	for {
+		if !buf.PrepareForReading() {
+			return nil
+		}
+
+		startPosition := buf.Position()
+		header, err := http2.ReadFrameHeader(buf)
+		if err != nil {
+			http2Log.Debugf("failed to read frame header, %v", err)
+			if buf.SkipCurrentElement() {
+				break
+			}
+			continue
+		}
+		http2Log.Debugf("current reading buffer data id: %d, seq: %d", startPosition.DataID(), startPosition.Seq())
+
+		var protocolBreak bool
+		var result enums.ParseResult
+		switch header.Type {
+		case http2.FrameHeaders:
+			result, protocolBreak, _ = r.handleHeader(&header, startPosition, http2Metrics, buf)
+		case http2.FrameData:
+			result, protocolBreak, _ = r.handleData(&header, startPosition, http2Metrics, buf)
+		default:
+			tmp := make([]byte, header.Length)
+			if err := buf.ReadUntilBufferFull(tmp); err != nil {
+				if errors.Is(err, buffer.ErrNotComplete) {
+					result = enums.ParseResultSkipPackage
+				} else {
+					protocolBreak = true
+				}
+			} else {
+				result = enums.ParseResultSuccess
+			}
+		}
+
+		// if the protocol break, then stop the loop and notify the caller to skip analyze all data(just sending the detail)
+		if protocolBreak {
+			http2Log.Warnf("the HTTP/2 protocol break, maybe not tracing the connection from beginning, skip all data analyze in this connection, "+
+				"connection ID: %d", http2Metrics.connectionID)
+			helper.ProtocolBreak = true
+			break
+		}
+
+		finishReading := false
+		switch result {
+		case enums.ParseResultSuccess:
+			finishReading = buf.RemoveReadElements()
+		case enums.ParseResultSkipPackage:
+			finishReading = buf.SkipCurrentElement()
+		}
+
+		if finishReading {
+			break
+		}
+	}
+
+	return nil
+}
+
+func (r *HTTP2Protocol) handleHeader(header *http2.FrameHeader, startPos *buffer.Position,
+	metrics *HTTP2Metrics, buf *buffer.Buffer) (enums.ParseResult, bool, error) {
+	bytes := make([]byte, header.Length)
+	if err := buf.ReadUntilBufferFull(bytes); err != nil {
+		return enums.ParseResultSkipPackage, false, err
+	}
+	headerData, err := metrics.hpackDecoder.DecodeFull(bytes)
+	if err != nil {
+		// reading the header failure, maybe not tracing the connection from beginning
+		return enums.ParseResultSkipPackage, true, err
+	}
+	// saving stream
+	streaming := metrics.streams[header.StreamID]
+	headers := r.parseHeaders(headerData)
+	if streaming == nil {
+		streaming = &HTTP2Streaming{
+			reqHeader:       headers,
+			respHeader:      make(map[string]string),
+			reqHeaderBuffer: buf.Slice(true, startPos, buf.Position()),
+		}
+		metrics.streams[header.StreamID] = streaming
+		return enums.ParseResultSuccess, false, nil
+	}
+
+	status, contains := headers[":status"]
+	if contains {
+		streaming.isInResponse = true
+		code, err := strconv.ParseInt(status, 10, 64)
+		if err != nil {
+			log.Warnf("cannot parse status code: %s", status)
+			code = 200
+		}
+		streaming.status = int(code)
+	}
+
+	if !streaming.isInResponse {
+		r.appendHeaders(streaming.reqHeader, headers)
+		streaming.reqHeaderBuffer = buffer.CombineSlices(true, streaming.reqHeaderBuffer, buf.Slice(true, startPos, buf.Position()))
+		return enums.ParseResultSuccess, false, nil
+	}
+
+	r.appendHeaders(streaming.respHeader, headers)
+	streaming.respHeaderBuffer = buffer.CombineSlices(true, streaming.respHeaderBuffer, buf.Slice(true, startPos, buf.Position()))
+
+	// is end of stream and in the response
+	if header.Flags.Has(http2.FlagHeadersEndStream) {
+		// should be end of the stream and send to the protocol
+		r.handleWholeStream(streaming)
+		// delete streaming
+		delete(metrics.streams, header.StreamID)
+	}
+	return enums.ParseResultSuccess, false, nil
+}
+
+func (r *HTTP2Protocol) validateIsStreamOpenTooLong(metrics *HTTP2Metrics, id uint32, streaming *HTTP2Streaming) {
+	// if in the response mode or the request body is not nil, then skip
+	if streaming.isInResponse || streaming.reqBodyBuffer == nil {
+		return
+	}
+
+	// is the body sending too long, then split the stream
+	if time.Since(host.Time(streaming.respBodyBuffer.FirstSocketBuffer().StartTime())) > maxHTTP2StreamingTime {
+		http2Log.Infof("detect the HTTP/2 stream is too long, split the stream, connection ID: %d, stream ID: %d, headers: %v",
+			metrics.connectionID, id, streaming.reqHeader)
+
+		r.handleWholeStream(streaming)
+
+		// clean sent buffers
+		if streaming.reqBodyBuffer != nil {
+			streaming.reqBodyBuffer.Clean()
+		}
+	}
+}
+
+func (r *HTTP2Protocol) handleWholeStream(stream *HTTP2Streaming) {
+	detailEvents := make([]*events.SocketDetailEvent, 0)
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, stream.reqHeaderBuffer)
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, stream.reqBodyBuffer)
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, stream.respHeaderBuffer)
+	detailEvents = appendSocketDetailsFromBuffer(detailEvents, stream.respBodyBuffer)
+
+	if len(detailEvents) == 0 {
+		http2Log.Warnf("cannot found any detail events for HTTP/2 protocol, data id: %d-%d",
+			stream.reqHeaderBuffer.FirstSocketBuffer().DataID(), stream.respBodyBuffer.LastSocketBuffer().DataID())
+		return
+	}
+
+	forwarder.SendTransferProtocolEvent(r.ctx, detailEvents, &v3.AccessLogProtocolLogs{
+		Protocol: &v3.AccessLogProtocolLogs_Http{
+			Http: &v3.AccessLogHTTPProtocol{
+				StartTime: forwarder.BuildOffsetTimestamp(r.firstDetail(stream.reqBodyBuffer, detailEvents[0]).StartTime),
+				EndTime:   forwarder.BuildOffsetTimestamp(detailEvents[len(detailEvents)-1].EndTime),
+				Version:   v3.AccessLogHTTPProtocolVersion_HTTP2,
+				Request: &v3.AccessLogHTTPProtocolRequest{
+					Method:             r.parseHTTPMethod(stream),
+					Path:               stream.reqHeader[":path"],
+					SizeOfHeadersBytes: r.bufferSizeOfZero(stream.reqHeaderBuffer),
+					SizeOfBodyBytes:    r.bufferSizeOfZero(stream.reqBodyBuffer),
+
+					Trace: analyzeTraceInfo(func(key string) string {
+						return stream.reqHeader[key]
+					}, http2Log),
+				},
+				Response: &v3.AccessLogHTTPProtocolResponse{
+					StatusCode:         int32(stream.status),
+					SizeOfHeadersBytes: r.bufferSizeOfZero(stream.respHeaderBuffer),
+					SizeOfBodyBytes:    r.bufferSizeOfZero(stream.respBodyBuffer),
+				},
+			},
+		},
+	})
+}
+
+func (r *HTTP2Protocol) parseHTTPMethod(streaming *HTTP2Streaming) v3.AccessLogHTTPProtocolRequestMethod {
+	method := streaming.reqHeader[":method"]
+	if method == "" {
+		return v3.AccessLogHTTPProtocolRequestMethod_Get
+	}
+
+	return transformHTTPMethod(strings.ToUpper(method))
+}
+
+func (r *HTTP2Protocol) firstDetail(buf *buffer.Buffer, def *events.SocketDetailEvent) *events.SocketDetailEvent {
+	if buf == nil || buf.Details() == nil || buf.Details().Len() == 0 {
+		return def
+	}
+	return buf.Details().Front().Value.(*events.SocketDetailEvent)
+}
+
+func (r *HTTP2Protocol) bufferSizeOfZero(buf *buffer.Buffer) uint64 {
+	if buf == nil {
+		return 0
+	}
+	return uint64(buf.DataSize())
+}
+
+func (r *HTTP2Protocol) appendHeaders(exist, needAppends map[string]string) {
+	for k, v := range needAppends {
+		exist[k] = v
+	}
+}
+
+func (r *HTTP2Protocol) handleData(header *http2.FrameHeader, startPos *buffer.Position,
+	metrics *HTTP2Metrics, buf *buffer.Buffer) (enums.ParseResult, bool, error) {
+	bytes := make([]byte, header.Length)
+	streaming := metrics.streams[header.StreamID]
+	if streaming == nil {
+		// cannot found the stream, maybe not tracing the connection from beginning
+		return enums.ParseResultSkipPackage, true, nil
+	}
+	if err := buf.ReadUntilBufferFull(bytes); err != nil {
+		return enums.ParseResultSkipPackage, false, err
+	}
+	if !streaming.isInResponse {
+		streaming.reqBodyBuffer = buffer.CombineSlices(true, streaming.reqBodyBuffer, buf.Slice(true, startPos, buf.Position()))
+	} else {
+		streaming.respBodyBuffer = buffer.CombineSlices(true, streaming.respBodyBuffer, buf.Slice(true, startPos, buf.Position()))
+	}
+
+	r.validateIsStreamOpenTooLong(metrics, header.StreamID, streaming)
+	return enums.ParseResultSuccess, false, nil
+}
+
+func (r *HTTP2Protocol) parseHeaders(headers []hpack.HeaderField) map[string]string {
+	result := make(map[string]string)
+	for _, header := range headers {
+		result[header.Name] = header.Value
+	}
+	return result
+}
diff --git a/pkg/accesslog/collector/protocols/protocol.go b/pkg/accesslog/collector/protocols/protocol.go
new file mode 100644
index 0000000..4c415c2
--- /dev/null
+++ b/pkg/accesslog/collector/protocols/protocol.go
@@ -0,0 +1,92 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package protocols
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/tracing"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+var registeredProtocols = make(map[enums.ConnectionProtocol]func(ctx *common.AccessLogContext) Protocol)
+
+type ProtocolManager struct {
+	protocols map[enums.ConnectionProtocol]Protocol
+}
+
+func NewProtocolManager(ctx *common.AccessLogContext) *ProtocolManager {
+	protocols := make(map[enums.ConnectionProtocol]Protocol)
+	for protocol, generator := range registeredProtocols {
+		protocols[protocol] = generator(ctx)
+	}
+	return &ProtocolManager{protocols: protocols}
+}
+
+func (a *ProtocolManager) GetProtocol(protocol enums.ConnectionProtocol) Protocol {
+	return a.protocols[protocol]
+}
+
+type ProtocolMetrics interface {
+}
+
+type AnalyzeHelper struct {
+	ProtocolBreak bool
+}
+
+type Protocol interface {
+	GenerateConnection(connectionID uint64) ProtocolMetrics
+	Analyze(metrics ProtocolMetrics, buffer *buffer.Buffer, helper *AnalyzeHelper) error
+}
+
+func appendSocketDetailsFromBuffer(result []*events.SocketDetailEvent, buf *buffer.Buffer) []*events.SocketDetailEvent {
+	if buf.DetailLength() == 0 {
+		return result
+	}
+	for e := buf.Details().Front(); e != nil; e = e.Next() {
+		if len(result) > 0 && result[len(result)-1] == e.Value {
+			continue
+		}
+		result = append(result, e.Value.(*events.SocketDetailEvent))
+	}
+	return result
+}
+
+func analyzeTraceInfo(fetcher func(key string) string, protocolLog *logger.Logger) *v3.AccessLogTraceInfo {
+	context, err := tracing.AnalyzeTracingContext(func(key string) string {
+		return fetcher(key)
+	})
+	if err != nil {
+		protocolLog.Warnf("analyze tracing context error: %v", err)
+		return nil
+	}
+	if context == nil {
+		return nil
+	}
+
+	return &v3.AccessLogTraceInfo{
+		TraceId:        context.TraceID(),
+		TraceSegmentId: context.TraceSegmentID(),
+		SpanId:         context.SpanID(),
+		Provider:       context.Provider().AccessLogType,
+	}
+}
diff --git a/pkg/accesslog/collector/protocols/queue.go b/pkg/accesslog/collector/protocols/queue.go
new file mode 100644
index 0000000..2c12c7a
--- /dev/null
+++ b/pkg/accesslog/collector/protocols/queue.go
@@ -0,0 +1,282 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package protocols
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"sync"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+
+	"github.com/docker/go-units"
+
+	cmap "github.com/orcaman/concurrent-map"
+)
+
+var maxBufferExpireDuration = time.Minute
+
+var log = logger.GetLogger("accesslog", "collector", "protocols")
+
+type AnalyzeQueue struct {
+	context      *common.AccessLogContext
+	eventQueue   *btf.EventQueue
+	perCPUBuffer int64
+}
+
+func NewAnalyzeQueue(ctx *common.AccessLogContext) (*AnalyzeQueue, error) {
+	perCPUBufferSize, err := units.RAMInBytes(ctx.Config.ProtocolAnalyze.PerCPUBufferSize)
+	if err != nil {
+		return nil, err
+	}
+	if int(perCPUBufferSize) < os.Getpagesize() {
+		return nil, fmt.Errorf("the cpu buffer must bigger than %dB", os.Getpagesize())
+	}
+	if ctx.Config.ProtocolAnalyze.Parallels < 1 {
+		return nil, fmt.Errorf("the parallels cannot be small than 1")
+	}
+	if ctx.Config.ProtocolAnalyze.QueueSize < 1 {
+		return nil, fmt.Errorf("the queue size be small than 1")
+	}
+
+	return &AnalyzeQueue{
+		context:      ctx,
+		perCPUBuffer: perCPUBufferSize,
+		eventQueue: btf.NewEventQueue(ctx.Config.ProtocolAnalyze.Parallels, ctx.Config.ProtocolAnalyze.QueueSize, func() btf.PartitionContext {
+			return NewPartitionContext(ctx)
+		}),
+	}, nil
+}
+
+func (q *AnalyzeQueue) Start(ctx context.Context) {
+	q.eventQueue.RegisterReceiver(q.context.BPF.SocketDetailDataQueue, int(q.perCPUBuffer), func() interface{} {
+		return &events.SocketDetailEvent{}
+	}, func(data interface{}) string {
+		return fmt.Sprintf("%d", data.(*events.SocketDetailEvent).GetConnectionID())
+	})
+	q.eventQueue.RegisterReceiver(q.context.BPF.SocketDataUploadEventQueue, int(q.perCPUBuffer), func() interface{} {
+		return &events.SocketDataUploadEvent{}
+	}, func(data interface{}) string {
+		return fmt.Sprintf("%d", data.(*events.SocketDataUploadEvent).ConnectionID)
+	})
+
+	q.eventQueue.Start(ctx, q.context.BPF.Linker)
+}
+
+type PartitionContext struct {
+	context     *common.AccessLogContext
+	protocolMgr *ProtocolManager
+	connections cmap.ConcurrentMap
+
+	analyzeLocker sync.Mutex
+}
+
+func newPartitionConnection(protocolMgr *ProtocolManager, conID, randomID uint64, protocol enums.ConnectionProtocol) *PartitionConnection {
+	analyzer := protocolMgr.GetProtocol(protocol)
+	return &PartitionConnection{
+		connectionID:     conID,
+		randomID:         randomID,
+		dataBuffer:       buffer.NewBuffer(),
+		protocol:         protocol,
+		protocolAnalyzer: analyzer,
+		protocolMetrics:  analyzer.GenerateConnection(conID),
+	}
+}
+
+func NewPartitionContext(ctx *common.AccessLogContext) *PartitionContext {
+	pc := &PartitionContext{
+		context:     ctx,
+		protocolMgr: NewProtocolManager(ctx),
+		connections: cmap.New(),
+	}
+	ctx.ConnectionMgr.RegisterProcessor(pc)
+	return pc
+}
+
+func (p *PartitionContext) OnConnectionClose(event *events.SocketCloseEvent, closeCallback common.ConnectionProcessFinishCallback) {
+	conn, exist := p.connections.Get(p.buildConnectionKey(event.GetConnectionID(), event.GetRandomID()))
+	if !exist {
+		closeCallback()
+		return
+	}
+	connection := conn.(*PartitionConnection)
+	connection.closeCallback = closeCallback
+	connection.closed = true
+}
+
+func (p *PartitionContext) Start(ctx context.Context) {
+	// process events with interval
+	flushDuration, _ := time.ParseDuration(p.context.Config.Flush.Period)
+	timeTicker := time.NewTicker(flushDuration)
+	go func() {
+		for {
+			select {
+			case <-timeTicker.C:
+				// process event with interval
+				p.processEvents()
+			case <-ctx.Done():
+				timeTicker.Stop()
+				return
+			}
+		}
+	}()
+
+	// delete the expired events
+	expireTicker := time.NewTicker(maxBufferExpireDuration)
+	go func() {
+		for {
+			select {
+			case <-expireTicker.C:
+				p.processExpireEvents()
+			case <-ctx.Done():
+				expireTicker.Stop()
+				return
+			}
+		}
+	}()
+}
+
+func (p *PartitionContext) Consume(data interface{}) {
+	switch event := data.(type) {
+	case *events.SocketDetailEvent:
+		log.Debugf("receive the socket detail event, connection ID: %d, random ID: %d, data id: %d, function name: %s",
+			event.ConnectionID, event.RandomID, event.DataID0, event.FunctionName)
+		if event.Protocol == enums.ConnectionProtocolUnknown {
+			// if the connection protocol is unknown, we just needs to add this into the kernel log
+			forwarder.SendTransferNoProtocolEvent(p.context, event)
+			return
+		}
+		connection := p.getConnectionContext(event.GetConnectionID(), event.GetRandomID(), event.Protocol)
+		connection.appendDetail(p.context, event)
+	case *events.SocketDataUploadEvent:
+		log.Debugf("receive the socket data event, connection ID: %d, random ID: %d, data id: %d, sequence: %d, protocol: %d",
+			event.ConnectionID, event.RandomID, event.DataID0, event.Sequence0, event.Protocol)
+		connection := p.getConnectionContext(event.ConnectionID, event.RandomID, event.Protocol)
+		connection.appendData(event)
+	}
+}
+
+func (p *PartitionContext) getConnectionContext(connectionID, randomID uint64, protocol enums.ConnectionProtocol) *PartitionConnection {
+	conKey := p.buildConnectionKey(connectionID, randomID)
+	conn, exist := p.connections.Get(conKey)
+	if exist {
+		return conn.(*PartitionConnection)
+	}
+	result := newPartitionConnection(p.protocolMgr, connectionID, randomID, protocol)
+	p.connections.Set(conKey, result)
+	return result
+}
+
+func (p *PartitionContext) buildConnectionKey(conID, ranID uint64) string {
+	return fmt.Sprintf("%d_%d", conID, ranID)
+}
+
+func (p *PartitionContext) processEvents() {
+	// it could be triggered by interval or reach counter
+	// if any trigger bean locked, the other one just ignore process
+	if !p.analyzeLocker.TryLock() {
+		return
+	}
+	defer p.analyzeLocker.Unlock()
+
+	closedConnections := make([]string, 0)
+	p.connections.IterCb(func(conKey string, con interface{}) {
+		info := con.(*PartitionConnection)
+		p.processConnectionEvents(info)
+
+		// if the connection already closed and not contains any buffer data, then delete the connection
+		if info.closed && info.dataBuffer.DataLength() == 0 {
+			if info.closeCallback != nil {
+				info.closeCallback()
+			}
+			closedConnections = append(closedConnections, conKey)
+		}
+	})
+
+	for _, conKey := range closedConnections {
+		p.connections.Remove(conKey)
+	}
+}
+
+func (p *PartitionContext) processExpireEvents() {
+	// the expiry must be mutual exclusion with events processor
+	p.analyzeLocker.Lock()
+	defer p.analyzeLocker.Unlock()
+
+	p.connections.IterCb(func(_ string, con interface{}) {
+		p.processConnectionExpireEvents(con.(*PartitionConnection))
+	})
+}
+
+func (p *PartitionContext) processConnectionExpireEvents(connection *PartitionConnection) {
+	if c := connection.dataBuffer.DeleteExpireEvents(maxBufferExpireDuration); c > 0 {
+		log.Debugf("total removed %d expired socket data events", c)
+	}
+}
+
+func (p *PartitionContext) processConnectionEvents(connection *PartitionConnection) {
+	if connection.skipAllDataAnalyze {
+		return
+	}
+	helper := &AnalyzeHelper{}
+	if err := connection.protocolAnalyzer.Analyze(connection.protocolMetrics, connection.dataBuffer, helper); err != nil {
+		log.Warnf("failed to analyze the %s protocol data: %v", connection.protocol.String(), err)
+	}
+
+	if helper.ProtocolBreak {
+		// notify the connection manager to skip analyze all data(just sending the detail)
+		connection.skipAllDataAnalyze = true
+		p.context.ConnectionMgr.SkipAllDataAnalyze(connection.connectionID, connection.randomID)
+		connection.dataBuffer.Clean()
+	}
+}
+
+type PartitionConnection struct {
+	connectionID, randomID uint64
+	dataBuffer             *buffer.Buffer
+	protocol               enums.ConnectionProtocol
+	protocolAnalyzer       Protocol
+	protocolMetrics        ProtocolMetrics
+	closed                 bool
+	closeCallback          common.ConnectionProcessFinishCallback
+	skipAllDataAnalyze     bool
+}
+
+func (p *PartitionConnection) appendDetail(ctx *common.AccessLogContext, detail *events.SocketDetailEvent) {
+	if p.skipAllDataAnalyze {
+		// if the connection is already skip all data analyze, then just send the detail event
+		forwarder.SendTransferNoProtocolEvent(ctx, detail)
+		return
+	}
+	p.dataBuffer.AppendDetailEvent(detail)
+}
+
+func (p *PartitionConnection) appendData(data buffer.SocketDataBuffer) {
+	if p.skipAllDataAnalyze {
+		return
+	}
+	p.dataBuffer.AppendDataEvent(data)
+}
diff --git a/pkg/accesslog/collector/tls.go b/pkg/accesslog/collector/tls.go
new file mode 100644
index 0000000..f6ce7d9
--- /dev/null
+++ b/pkg/accesslog/collector/tls.go
@@ -0,0 +1,87 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/module"
+	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/ssl"
+)
+
+var tlsLog = logger.GetLogger("access_log", "collector", "tls")
+
+var tlsCollectInstance = NewTLSCollector()
+
+type TLSCollector struct {
+	context            *common.AccessLogContext
+	monitoredProcesses map[int32]bool
+	linker             *btf.Linker
+}
+
+func NewTLSCollector() *TLSCollector {
+	return &TLSCollector{
+		monitoredProcesses: make(map[int32]bool),
+		linker:             btf.NewLinker(),
+	}
+}
+
+func (c *TLSCollector) Start(_ *module.Manager, context *common.AccessLogContext) error {
+	c.context = context
+	context.ConnectionMgr.AddProcessListener(c)
+	return nil
+}
+
+func (c *TLSCollector) Stop() {
+	if err := c.linker.Close(); err != nil {
+		tlsLog.Warnf("close linker failure, error: %v", err)
+	}
+	c.monitoredProcesses = make(map[int32]bool)
+	c.linker = btf.NewLinker()
+}
+
+func (c *TLSCollector) OnNewProcessMonitoring(pid int32) {
+	if _, ok := c.monitoredProcesses[pid]; ok {
+		return
+	}
+	c.monitoredProcesses[pid] = true
+
+	register := ssl.NewSSLRegister(int(pid), c.linker)
+
+	register.OpenSSL(c.context.BPF.OpensslSymaddrMap, c.context.BPF.OpensslWrite, c.context.BPF.OpensslWriteRet,
+		c.context.BPF.OpensslRead, c.context.BPF.OpensslReadRet)
+
+	register.OpenSSL(nil, c.context.BPF.OpensslWrite, c.context.BPF.OpensslWriteRet,
+		c.context.BPF.OpensslRead, c.context.BPF.OpensslReadRet)
+
+	register.GoTLS(c.context.BPF.GoTlsArgsSymaddrMap, c.context.BPF.GoTlsWrite, c.context.BPF.GoTlsWriteRet,
+		c.context.BPF.GoTlsRead, c.context.BPF.GoTlsReadRet)
+
+	register.Node(nil, c.context.BPF.NodeTlsSymaddrMap, c.context.BPF.OpensslWrite, c.context.BPF.OpensslWriteRet,
+		c.context.BPF.OpensslRead, c.context.BPF.OpensslReadRet, c.context.BPF.NodeTlsRetSsl, c.context.BPF.NodeTlsWrap, c.context.BPF.NodeTlsWrapRet)
+
+	if err := register.Execute(); err != nil {
+		tlsLog.Errorf("register TLS failure, pid: %d, error: %v", pid, err)
+		delete(c.monitoredProcesses, pid)
+	}
+}
+
+func (c *TLSCollector) OnProcessRemoved(pid int32) {
+	delete(c.monitoredProcesses, pid)
+}
diff --git a/pkg/accesslog/collector/transfer.go b/pkg/accesslog/collector/transfer.go
new file mode 100644
index 0000000..3aa9f24
--- /dev/null
+++ b/pkg/accesslog/collector/transfer.go
@@ -0,0 +1,77 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package collector
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/collector/protocols"
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/module"
+
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/link"
+)
+
+var transferCollectInstance = NewTransferCollector()
+
+type TransferCollector struct {
+	protocolQueue *protocols.AnalyzeQueue
+}
+
+func NewTransferCollector() *TransferCollector {
+	return &TransferCollector{}
+}
+
+func (t *TransferCollector) Start(_ *module.Manager, context *common.AccessLogContext) error {
+	queue, err := protocols.NewAnalyzeQueue(context)
+	if err != nil {
+		return err
+	}
+
+	t.protocolQueue = queue
+	t.protocolQueue.Start(context.RuntimeContext)
+
+	context.BPF.AddTracePoint("skb", "skb_copy_datagram_iovec", context.BPF.TracepointSkbCopyDatagramIovec)
+
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"security_socket_sendmsg": context.BPF.SecuritySocketSendmsg})
+	context.BPF.AddLink(link.Kprobe, map[string]*ebpf.Program{"security_socket_recvmsg": context.BPF.SecuritySocketRecvmsg})
+
+	context.BPF.AddTracePoint("syscalls", "sys_enter_write", context.BPF.TracepointEnterWrite)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_write", context.BPF.TracepointExitWrite)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_read", context.BPF.TracepointEnterRead)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_read", context.BPF.TracepointExitRead)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_sendto", context.BPF.TracepointEnterSendto)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_sendto", context.BPF.TracepointExitSendto)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_writev", context.BPF.TracepointEnterWritev)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_writev", context.BPF.TracepointExitWritev)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_sendmsg", context.BPF.TracepointEnterSendmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_sendmsg", context.BPF.TracepointExitSendmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_sendmmsg", context.BPF.TracepointEnterSendmmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_sendmmsg", context.BPF.TracepointExitSendmmsg)
+	context.BPF.AddSysCall("recv", context.BPF.SysRecv, context.BPF.SysRecvRet)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_recvfrom", context.BPF.TracepointEnterRecvfrom)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_recvfrom", context.BPF.TracepointExitRecvfrom)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_recvmsg", context.BPF.TracepointEnterRecvmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_recvmsg", context.BPF.TracepointExitRecvmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_enter_recvmmsg", context.BPF.TracepointEnterRecvmmsg)
+	context.BPF.AddTracePoint("syscalls", "sys_exit_recvmmsg", context.BPF.TracepointExitRecvmmsg)
+
+	return nil
+}
+
+func (t *TransferCollector) Stop() {
+}
diff --git a/pkg/process/finders/base/process.go b/pkg/accesslog/common/accesslog.go
similarity index 56%
copy from pkg/process/finders/base/process.go
copy to pkg/accesslog/common/accesslog.go
index fc3b46f..63f4c76 100644
--- a/pkg/process/finders/base/process.go
+++ b/pkg/accesslog/common/accesslog.go
@@ -15,27 +15,18 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package base
+package common
 
 import (
-	"github.com/shirou/gopsutil/process"
+	"context"
 
-	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/tools/profiling"
+	"github.com/apache/skywalking-rover/pkg/accesslog/bpf"
 )
 
-// DetectedProcess from the finder
-type DetectedProcess interface {
-	// Pid of process in host
-	Pid() int32
-	// OriginalProcess is works for query the process data
-	OriginalProcess() *process.Process
-	// Entity of process, is related with backend entity
-	Entity() *api.ProcessEntity
-	// DetectType define the process find type
-	DetectType() api.ProcessDetectType
-	// ProfilingStat of process
-	ProfilingStat() *profiling.Info
-	// ExposePorts define which ports are exposed
-	ExposePorts() []int
+type AccessLogContext struct {
+	BPF            *bpf.Loader
+	Queue          *Queue
+	ConnectionMgr  *ConnectionManager
+	Config         *Config
+	RuntimeContext context.Context
 }
diff --git a/pkg/process/finders/base/process.go b/pkg/accesslog/common/config.go
similarity index 54%
rename from pkg/process/finders/base/process.go
rename to pkg/accesslog/common/config.go
index fc3b46f..de1bcee 100644
--- a/pkg/process/finders/base/process.go
+++ b/pkg/accesslog/common/config.go
@@ -15,27 +15,29 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package base
+package common
 
-import (
-	"github.com/shirou/gopsutil/process"
+import "github.com/apache/skywalking-rover/pkg/module"
 
-	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/tools/profiling"
-)
+type Config struct {
+	module.Config
 
-// DetectedProcess from the finder
-type DetectedProcess interface {
-	// Pid of process in host
-	Pid() int32
-	// OriginalProcess is works for query the process data
-	OriginalProcess() *process.Process
-	// Entity of process, is related with backend entity
-	Entity() *api.ProcessEntity
-	// DetectType define the process find type
-	DetectType() api.ProcessDetectType
-	// ProfilingStat of process
-	ProfilingStat() *profiling.Info
-	// ExposePorts define which ports are exposed
-	ExposePorts() []int
+	Active          bool                  `mapstructure:"active"`
+	Flush           FlushConfig           `mapstructure:"flush"`
+	ProtocolAnalyze ProtocolAnalyzeConfig `mapstructure:"protocol_analyze"`
+}
+
+type FlushConfig struct {
+	MaxCountOneStream int    `mapstructure:"max_count"`
+	Period            string `mapstructure:"period"`
+}
+
+type ProtocolAnalyzeConfig struct {
+	PerCPUBufferSize string `mapstructure:"per_cpu_buffer"`
+	Parallels        int    `mapstructure:"parallels"`
+	QueueSize        int    `mapstructure:"queue_size"`
+}
+
+func (c *Config) IsActive() bool {
+	return c.Active
 }
diff --git a/pkg/accesslog/common/connection.go b/pkg/accesslog/common/connection.go
new file mode 100644
index 0000000..519f5e5
--- /dev/null
+++ b/pkg/accesslog/common/connection.go
@@ -0,0 +1,447 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package common
+
+import (
+	"errors"
+	"fmt"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/bpf"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/module"
+	"github.com/apache/skywalking-rover/pkg/process"
+	"github.com/apache/skywalking-rover/pkg/process/api"
+	"github.com/apache/skywalking-rover/pkg/process/finders/kubernetes"
+	"github.com/apache/skywalking-rover/pkg/tools"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/ip"
+
+	"github.com/cilium/ebpf"
+
+	cmap "github.com/orcaman/concurrent-map"
+
+	"k8s.io/apimachinery/pkg/util/cache"
+
+	v32 "skywalking.apache.org/repo/goapi/collect/common/v3"
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+const localAddressPairCacheTime = time.Hour * 6
+
+type addressProcessType int
+
+const (
+	addressProcessTypeUnknown addressProcessType = iota
+	addressProcessTypeLocal
+	addressProcessTypeKubernetes
+)
+
+type ConnectEventWithSocket struct {
+	*events.SocketConnectEvent
+	SocketPair *ip.SocketPair
+}
+
+type CloseEventWithNotify struct {
+	*events.SocketCloseEvent
+	allProcessorFinished bool
+}
+
+type ConnectionProcessFinishCallback func()
+
+type ConnectionProcessor interface {
+	OnConnectionClose(event *events.SocketCloseEvent, callback ConnectionProcessFinishCallback)
+}
+
+type ProcessListener interface {
+	OnNewProcessMonitoring(pid int32)
+	OnProcessRemoved(pid int32)
+}
+
+type ConnectionManager struct {
+	moduleMgr   *module.Manager
+	processOP   process.Operator
+	connections cmap.ConcurrentMap
+	// addressWithPid cache all local ip+port and pid mapping for match the process on the same host
+	// such as service mesh(process with envoy)
+	addressWithPid *cache.Expiring
+	// localIPWithPid cache all local monitoring process bind IP address
+	// for checking the remote address is local or not
+	localIPWithPid map[string]int32
+	// monitoringProcesses management all monitoring processes
+	monitoringProcesses map[int32][]api.ProcessInterface
+	// monitoring process map in BPF
+	processMonitorMap   *ebpf.Map
+	activeConnectionMap *ebpf.Map
+
+	processors       []ConnectionProcessor
+	processListeners []ProcessListener
+
+	// connection already close but the connection (protocols)log not build finished
+	allUnfinishedConnections map[string]*bool
+}
+
+func (c *ConnectionManager) RegisterProcessor(processor ConnectionProcessor) {
+	c.processors = append(c.processors, processor)
+}
+
+func (c *ConnectionManager) AddProcessListener(listener ProcessListener) {
+	c.processListeners = append(c.processListeners, listener)
+}
+
+type addressInfo struct {
+	pid         uint32
+	processType addressProcessType
+}
+
+type ConnectionInfo struct {
+	RPCConnection *v3.AccessLogConnection
+	MarkDeletable bool
+	PID           uint32
+}
+
+func NewConnectionManager(moduleMgr *module.Manager, bpfLoader *bpf.Loader) *ConnectionManager {
+	mgr := &ConnectionManager{
+		moduleMgr:                moduleMgr,
+		processOP:                moduleMgr.FindModule(process.ModuleName).(process.Operator),
+		connections:              cmap.New(),
+		addressWithPid:           cache.NewExpiring(),
+		localIPWithPid:           make(map[string]int32),
+		monitoringProcesses:      make(map[int32][]api.ProcessInterface),
+		processMonitorMap:        bpfLoader.ProcessMonitorControl,
+		activeConnectionMap:      bpfLoader.ActiveConnectionMap,
+		allUnfinishedConnections: make(map[string]*bool),
+	}
+	return mgr
+}
+
+func (c *ConnectionManager) Start() {
+	c.processOP.AddListener(c)
+}
+
+func (c *ConnectionManager) Stop() {
+	c.processOP.DeleteListener(c)
+}
+
+func (c *ConnectionManager) OnNewProcessExecuting(pid int32) {
+	// if the process should not be monitoring, then delete in the map
+	if !c.processOP.ShouldMonitor(pid) {
+		c.updateMonitorStatusForProcess(pid, false)
+	}
+}
+
+func (c *ConnectionManager) Find(event events.Event) *ConnectionInfo {
+	connectionKey := fmt.Sprintf("%d_%d", event.GetConnectionID(), event.GetRandomID())
+	data, exist := c.connections.Get(connectionKey)
+	if exist {
+		connection := data.(*ConnectionInfo)
+		c.connectionPostHandle(connection, event)
+		return connection
+	}
+	// is current is connected event, then getting the socket pair
+	if e, socket := getSocketPairFromConnectEvent(event); e != nil && socket != nil {
+		var localAddress, remoteAddress *v3.ConnectionAddress
+		localPID, _ := events.ParseConnectionID(event.GetConnectionID())
+		localAddress = c.buildAddressFromLocalKubernetesProcess(localPID, socket.SrcPort, addressProcessTypeKubernetes)
+		// trying to get the remote process if in the same host
+		remoteAddressInfo, ok := c.addressWithPid.Get(fmt.Sprintf("%s_%d", socket.DestIP, socket.DestPort))
+		if ok && remoteAddressInfo != nil {
+			address := remoteAddressInfo.(*addressInfo)
+			remoteAddress = c.buildAddressFromLocalKubernetesProcess(address.pid, socket.DestPort, address.processType)
+		} else {
+			remoteAddress = c.buildAddressFromRemote(socket.DestIP, socket.DestPort)
+		}
+		connection := c.buildConnection(e, socket, localAddress, remoteAddress)
+		c.connections.Set(connectionKey, connection)
+		return connection
+	}
+	return nil
+}
+
+func (c *ConnectionManager) connectionPostHandle(connection *ConnectionInfo, event events.Event) {
+	if connection == nil {
+		return
+	}
+	switch e := event.(type) {
+	case *CloseEventWithNotify:
+		if e.allProcessorFinished {
+			connection.MarkDeletable = true
+		} else {
+			// if not all processor finished, then add into the map
+			c.allUnfinishedConnections[fmt.Sprintf("%d_%d", event.GetConnectionID(), event.GetRandomID())] = &e.allProcessorFinished
+		}
+	case *events.SocketDetailEvent:
+		if e.SSL == 1 && connection.RPCConnection.TlsMode == v3.AccessLogConnectionTLSMode_Plain {
+			connection.RPCConnection.TlsMode = v3.AccessLogConnectionTLSMode_TLS
+		}
+	}
+}
+
+func (c *ConnectionManager) ProcessIsMonitor(pid uint32) bool {
+	return len(c.monitoringProcesses[int32(pid)]) > 0
+}
+
+func (c *ConnectionManager) buildConnection(event *events.SocketConnectEvent, socket *ip.SocketPair,
+	local, remote *v3.ConnectionAddress) *ConnectionInfo {
+	var role v32.DetectPoint
+	switch socket.Role {
+	case enums.ConnectionRoleClient:
+		role = v32.DetectPoint_client
+	case enums.ConnectionRoleServer:
+		role = v32.DetectPoint_server
+	}
+	connection := &v3.AccessLogConnection{
+		Local:   local,
+		Remote:  remote,
+		Role:    role,
+		TlsMode: v3.AccessLogConnectionTLSMode_Plain,
+	}
+	return &ConnectionInfo{
+		RPCConnection: connection,
+		PID:           event.PID,
+	}
+}
+
+func (c *ConnectionManager) buildAddressFromLocalKubernetesProcess(pid uint32, port uint16, _ addressProcessType) *v3.ConnectionAddress {
+	for _, pi := range c.monitoringProcesses[int32(pid)] {
+		if pi.DetectType() == api.Kubernetes {
+			entity := pi.Entity()
+			podContainer := pi.DetectProcess().(*kubernetes.Process).PodContainer()
+			return &v3.ConnectionAddress{
+				Address: &v3.ConnectionAddress_Kubernetes{
+					Kubernetes: &v3.KubernetesProcessAddress{
+						ServiceName:   entity.ServiceName,
+						PodName:       podContainer.Pod.Name,
+						ContainerName: podContainer.ContainerSpec.Name,
+						ProcessName:   entity.ProcessName,
+						Port:          int32(port),
+					},
+				},
+			}
+		}
+	}
+	return nil
+}
+
+func (c *ConnectionManager) buildAddressFromRemote(ipHost string, port uint16) *v3.ConnectionAddress {
+	return &v3.ConnectionAddress{
+		Address: &v3.ConnectionAddress_Ip{
+			Ip: &v3.IPAddress{
+				Host: ipHost,
+				Port: int32(port),
+			},
+		},
+	}
+}
+
+func (c *ConnectionManager) OnConnectionClose(event *events.SocketCloseEvent) *CloseEventWithNotify {
+	result := &CloseEventWithNotify{
+		SocketCloseEvent:     event,
+		allProcessorFinished: false,
+	}
+	processCount := len(c.processors)
+	for _, l := range c.processors {
+		l.OnConnectionClose(event, func() {
+			processCount--
+			if processCount > 0 {
+				return
+			}
+			result.allProcessorFinished = true
+		})
+	}
+	return result
+}
+
+func (c *ConnectionManager) OnConnectEvent(event *events.SocketConnectEvent, pair *ip.SocketPair) {
+	// only adding the local ip port when remote is local address
+	if tp := c.isLocalTarget(pair); tp != addressProcessTypeUnknown {
+		c.addressWithPid.Set(fmt.Sprintf("%s_%d", pair.SrcIP, pair.SrcPort), &addressInfo{
+			pid:         event.PID,
+			processType: tp,
+		}, localAddressPairCacheTime)
+	}
+}
+
+func (c *ConnectionManager) isLocalTarget(pair *ip.SocketPair) addressProcessType {
+	destIP := pair.DestIP
+	if tools.IsLocalHostAddress(destIP) {
+		return addressProcessTypeLocal
+	}
+	if _, exist := c.localIPWithPid[destIP]; exist {
+		return addressProcessTypeKubernetes
+	}
+	return addressProcessTypeUnknown
+}
+
+func (c *ConnectionManager) AddNewProcess(pid int32, entities []api.ProcessInterface) {
+	// adding monitoring process and IP addresses
+	c.monitoringProcesses[pid] = entities
+	c.updateMonitorStatusForProcess(pid, true)
+	for _, entity := range entities {
+		for _, host := range entity.ExposeHosts() {
+			c.localIPWithPid[host] = pid
+		}
+	}
+	for _, l := range c.processListeners {
+		l.OnNewProcessMonitoring(pid)
+	}
+}
+
+func (c *ConnectionManager) RemoveProcess(pid int32, entities []api.ProcessInterface) {
+	// delete monitoring process and IP addresses
+	delete(c.monitoringProcesses, pid)
+	c.updateMonitorStatusForProcess(pid, false)
+	for _, entity := range entities {
+		for _, host := range entity.ExposeHosts() {
+			delete(c.localIPWithPid, host)
+		}
+	}
+	for _, l := range c.processListeners {
+		l.OnProcessRemoved(pid)
+	}
+}
+
+func (c *ConnectionManager) RecheckAllProcesses(processes map[int32][]api.ProcessInterface) {
+	// checking the monitoring process
+	c.monitoringProcesses = processes
+	// for-each the existing monitored map, it should not be monitored, then remote it
+	iterate := c.processMonitorMap.Iterate()
+	processInBPF := make(map[int32]bool)
+	var pid uint32
+	var monitor uint32
+	for iterate.Next(&pid, &monitor) {
+		processInBPF[int32(pid)] = true
+	}
+
+	// make sure BPF and user space are consistent
+	for pid := range processInBPF {
+		if _, ok := c.monitoringProcesses[pid]; !ok {
+			c.updateMonitorStatusForProcess(pid, false)
+			for _, l := range c.processListeners {
+				l.OnProcessRemoved(pid)
+			}
+		}
+	}
+	for pid := range c.monitoringProcesses {
+		if _, ok := processInBPF[pid]; !ok {
+			c.updateMonitorStatusForProcess(pid, true)
+			for _, l := range c.processListeners {
+				l.OnNewProcessMonitoring(pid)
+			}
+		}
+	}
+
+	// update all IP addresses
+	result := make(map[string]int32)
+	for _, p := range processes {
+		for _, entity := range p {
+			for _, host := range entity.ExposeHosts() {
+				result[host] = entity.Pid()
+			}
+		}
+	}
+
+	c.localIPWithPid = result
+}
+
+func (c *ConnectionManager) updateMonitorStatusForProcess(pid int32, monitor bool) {
+	var err error
+	if monitor {
+		err = c.processMonitorMap.Update(pid, uint32(1), ebpf.UpdateAny)
+	} else {
+		err = c.processMonitorMap.Delete(pid)
+	}
+	if err != nil {
+		if !monitor && errors.Is(err, ebpf.ErrKeyNotExist) {
+			return
+		}
+		log.Warnf("failed to update the process %d monitor status to %t: %v", pid, monitor, err)
+	}
+}
+
+// OnBuildConnectionLogFinished notify the connection log build finished
+func (c *ConnectionManager) OnBuildConnectionLogFinished() {
+	// delete all connections which marked as deletable
+	// all deletable connection events been sent
+	deletableConnections := make([]string, 0)
+	c.connections.IterCb(func(key string, v interface{}) {
+		con, ok := v.(*ConnectionInfo)
+		if !ok || con == nil {
+			return
+		}
+		// already mark as deletable or process not monitoring
+		shouldDelete := con.MarkDeletable || len(c.monitoringProcesses[int32(con.PID)]) == 0
+
+		if shouldDelete {
+			deletableConnections = append(deletableConnections, key)
+		}
+	})
+
+	deleteFromUnfinished := make([]string, 0)
+	for conKey, processorFinished := range c.allUnfinishedConnections {
+		if *processorFinished {
+			deletableConnections = append(deletableConnections, conKey)
+			deleteFromUnfinished = append(deleteFromUnfinished, conKey)
+		}
+	}
+	for _, key := range deleteFromUnfinished {
+		delete(c.allUnfinishedConnections, key)
+	}
+
+	for _, key := range deletableConnections {
+		c.connections.Remove(key)
+	}
+}
+
+func (c *ConnectionManager) SkipAllDataAnalyze(conID, ranID uint64) {
+	var activateConn ActiveConnection
+	if err := c.activeConnectionMap.Lookup(conID, &activateConn); err != nil {
+		log.Warnf("cannot found the active connection: %d-%d", conID, ranID)
+		return
+	}
+	if activateConn.RandomID != ranID {
+		// make sure the connection is the same
+		return
+	}
+
+	activateConn.SkipDataUpload = 1
+	if err := c.activeConnectionMap.Update(conID, activateConn, ebpf.UpdateAny); err != nil {
+		log.Warnf("failed to update the active connection: %d-%d", conID, ranID)
+	}
+}
+
+func getSocketPairFromConnectEvent(event events.Event) (*events.SocketConnectEvent, *ip.SocketPair) {
+	if e, ok := event.(*ConnectEventWithSocket); ok {
+		return e.SocketConnectEvent, e.SocketPair
+	}
+	return nil, nil
+}
+
+type ActiveConnection struct {
+	RandomID       uint64
+	PID            uint32
+	SocketFD       uint32
+	Role           uint32
+	SocketFamily   uint32
+	Protocol       uint8
+	SSL            uint8
+	SkipDataUpload uint8
+	// PAD for make sure it have same size when marshal data to the BPF
+	PAD0 uint8
+	PAD1 uint32
+}
diff --git a/pkg/accesslog/common/queue.go b/pkg/accesslog/common/queue.go
new file mode 100644
index 0000000..0cf15c8
--- /dev/null
+++ b/pkg/accesslog/common/queue.go
@@ -0,0 +1,141 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package common
+
+import (
+	"context"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/logger"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+var log = logger.GetLogger("access_log", "common")
+
+type KernelLog struct {
+	Type  LogType
+	Event events.Event
+}
+
+type ProtocolLog struct {
+	KernelLogs []*events.SocketDetailEvent
+	Protocol   *v3.AccessLogProtocolLogs
+}
+
+type Queue struct {
+	kernelLogs   chan *KernelLog
+	protocolLogs chan *ProtocolLog
+
+	maxFlushCount int
+	period        time.Duration
+	consumer      QueueConsumer
+	consumeLock   *sync.Mutex
+
+	dropKernelLogCount   int64
+	dropProtocolLogCount int64
+}
+
+type QueueConsumer interface {
+	Consume(kernels chan *KernelLog, protocols chan *ProtocolLog)
+}
+
+func NewQueue(maxFlushCount int, period time.Duration, consumer QueueConsumer) *Queue {
+	return &Queue{
+		kernelLogs:    make(chan *KernelLog, maxFlushCount*3),
+		protocolLogs:  make(chan *ProtocolLog, maxFlushCount*3),
+		maxFlushCount: maxFlushCount,
+		period:        period,
+		consumer:      consumer,
+		consumeLock:   &sync.Mutex{},
+	}
+}
+
+func (q *Queue) AppendKernelLog(tp LogType, event events.Event) {
+	select {
+	case q.kernelLogs <- &KernelLog{
+		Type:  tp,
+		Event: event,
+	}:
+	default:
+		atomic.AddInt64(&q.dropKernelLogCount, 1)
+		return
+	}
+	q.consumeIfNeed()
+}
+
+func (q *Queue) AppendProtocolLog(kernelLogs []*events.SocketDetailEvent, protocol *v3.AccessLogProtocolLogs) {
+	select {
+	case q.protocolLogs <- &ProtocolLog{
+		KernelLogs: kernelLogs,
+		Protocol:   protocol,
+	}:
+	default:
+		atomic.AddInt64(&q.dropProtocolLogCount, 1)
+		return
+	}
+	q.consumeIfNeed()
+}
+
+func (q *Queue) consumeIfNeed() {
+	if len(q.kernelLogs)+len(q.protocolLogs) >= q.maxFlushCount {
+		go q.consume()
+	}
+}
+
+func (q *Queue) Start(ctx context.Context) {
+	go func() {
+		timeTicker := time.NewTicker(q.period)
+		for {
+			select {
+			case <-timeTicker.C:
+				q.consume()
+			case <-ctx.Done():
+				timeTicker.Stop()
+				return
+			}
+		}
+	}()
+	go func() {
+		timeTicker := time.NewTicker(time.Second * 5)
+		for {
+			select {
+			case <-timeTicker.C:
+				if q.dropKernelLogCount > 0 || q.dropProtocolLogCount > 0 {
+					kernelLogCount := atomic.SwapInt64(&q.dropKernelLogCount, 0)
+					protocolLogCount := atomic.SwapInt64(&q.dropProtocolLogCount, 0)
+					log.Warnf("drop kernel log count: %d, drop protocol log count: %d", kernelLogCount, protocolLogCount)
+				}
+			case <-ctx.Done():
+				timeTicker.Stop()
+				return
+			}
+		}
+	}()
+}
+
+func (q *Queue) consume() {
+	if !q.consumeLock.TryLock() {
+		return
+	}
+	defer q.consumeLock.Unlock()
+	q.consumer.Consume(q.kernelLogs, q.protocolLogs)
+}
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/pkg/accesslog/common/type.go
similarity index 89%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to pkg/accesslog/common/type.go
index 555705c..53f288f 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/pkg/accesslog/common/type.go
@@ -15,11 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
+package common
 
-type ParseResult int
+type LogType int
 
 const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
+	LogTypeConnect LogType = iota
+	LogTypeKernelTransfer
+	LogTypeClose
 )
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/pkg/accesslog/events/base.go
similarity index 75%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to pkg/accesslog/events/base.go
index 555705c..89cc055 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/pkg/accesslog/events/base.go
@@ -15,11 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
+package events
 
-type ParseResult int
+import "time"
 
-const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
-)
+type Event interface {
+	GetConnectionID() uint64
+	GetRandomID() uint64
+	Timestamp() time.Time
+}
+
+func ParseConnectionID(connectionID uint64) (pid, socketFD uint32) {
+	return uint32(connectionID >> 32), uint32(connectionID & 0xFFFFFFFF)
+}
diff --git a/pkg/boot/register.go b/pkg/accesslog/events/close.go
similarity index 63%
copy from pkg/boot/register.go
copy to pkg/accesslog/events/close.go
index 8f0d64d..de24669 100644
--- a/pkg/boot/register.go
+++ b/pkg/accesslog/events/close.go
@@ -15,20 +15,33 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package boot
+package events
 
 import (
-	"github.com/apache/skywalking-rover/pkg/core"
-	"github.com/apache/skywalking-rover/pkg/logger"
-	"github.com/apache/skywalking-rover/pkg/module"
-	"github.com/apache/skywalking-rover/pkg/process"
-	"github.com/apache/skywalking-rover/pkg/profiling"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/tools/host"
 )
 
-func init() {
-	// register all active module
-	module.Register(logger.NewModule())
-	module.Register(core.NewModule())
-	module.Register(process.NewModule())
-	module.Register(profiling.NewModule())
+type SocketCloseEvent struct {
+	ConnectionID uint64
+	RandomID     uint64
+
+	StartTime uint64
+	EndTime   uint64
+	PID       uint32
+	SocketFD  uint32
+	Success   uint32
+}
+
+func (c *SocketCloseEvent) GetConnectionID() uint64 {
+	return c.ConnectionID
+}
+
+func (c *SocketCloseEvent) GetRandomID() uint64 {
+	return c.RandomID
+}
+
+func (c *SocketCloseEvent) Timestamp() time.Time {
+	return host.Time(c.StartTime)
 }
diff --git a/pkg/accesslog/events/connect.go b/pkg/accesslog/events/connect.go
new file mode 100644
index 0000000..3e2a72b
--- /dev/null
+++ b/pkg/accesslog/events/connect.go
@@ -0,0 +1,59 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package events
+
+import (
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/tools/host"
+)
+
+type SocketConnectEvent struct {
+	ConID                 uint64
+	RandomID              uint64
+	StartTime             uint64
+	EndTime               uint64
+	PID                   uint32
+	SocketFD              uint32
+	FuncName              uint8
+	Role                  uint8
+	SocketFamily          uint8
+	ConnectSuccess        uint8
+	Pad0                  uint32
+	RemoteAddrV4          uint32
+	RemoteAddrV6          [16]uint8
+	RemoteAddrPort        uint32
+	LocalAddrV4           uint32
+	LocalAddrV6           [16]uint8
+	LocalAddrPort         uint32
+	ConnTrackUpstreamPort uint32
+	ConnTrackUpstreamIPh  uint64
+	ConnTrackUpstreamIPl  uint64
+}
+
+func (c *SocketConnectEvent) GetConnectionID() uint64 {
+	return c.ConID
+}
+
+func (c *SocketConnectEvent) GetRandomID() uint64 {
+	return c.RandomID
+}
+
+func (c *SocketConnectEvent) Timestamp() time.Time {
+	return host.Time(c.StartTime)
+}
diff --git a/pkg/profiling/task/network/analyze/events/data.go b/pkg/accesslog/events/data.go
similarity index 53%
copy from pkg/profiling/task/network/analyze/events/data.go
copy to pkg/accesslog/events/data.go
index 46b0ae2..747ff9f 100644
--- a/pkg/profiling/task/network/analyze/events/data.go
+++ b/pkg/accesslog/events/data.go
@@ -19,42 +19,14 @@ package events
 
 import (
 	"fmt"
-)
 
-type SocketDataBuffer interface {
-	// GenerateConnectionID for identity the buffer belong which connection
-	GenerateConnectionID() string
-	// BufferData of the buffer
-	BufferData() []byte
-	// TotalSize of socket data, the data may exceed the size of the BufferData()
-	TotalSize() uint64
-	// Direction of the data, send or receive
-	Direction() SocketDataDirection
-	// BufferStartPosition the buffer start index
-	BufferStartPosition() int
-	// BufferLen the buffer data length
-	BufferLen() int
-	// DataID data id of the buffer
-	DataID() uint64
-	// DataSequence the data sequence under same data id
-	DataSequence() int
-	// IsStart this buffer is start of the same data id
-	IsStart() bool
-	// IsFinished this buffer is finish of the same data id
-	IsFinished() bool
-	// HaveReduceDataAfterChunk check have reduced data after current buffer
-	HaveReduceDataAfterChunk() bool
-
-	// StartTime the data start timestamp
-	StartTime() uint64
-	// EndTime the data end timestamp
-	EndTime() uint64
-}
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+)
 
 type SocketDataUploadEvent struct {
-	Protocol     ConnectionProtocol
+	Protocol     enums.ConnectionProtocol
 	HaveReduce   uint8
-	Direction0   SocketDataDirection
+	Direction0   enums.SocketDataDirection
 	Finished     uint8
 	Sequence0    uint16
 	DataLen      uint16
@@ -87,7 +59,7 @@ func (s *SocketDataUploadEvent) EndTime() uint64 {
 	return s.EndTime0
 }
 
-func (s *SocketDataUploadEvent) Direction() SocketDataDirection {
+func (s *SocketDataUploadEvent) Direction() enums.SocketDataDirection {
 	return s.Direction0
 }
 
@@ -118,38 +90,3 @@ func (s *SocketDataUploadEvent) TotalSize() uint64 {
 func (s *SocketDataUploadEvent) HaveReduceDataAfterChunk() bool {
 	return s.HaveReduce == 1
 }
-
-type SocketDataEventLimited struct {
-	SocketDataBuffer
-	From int
-	Size int
-}
-
-func (s *SocketDataEventLimited) BufferData() []byte {
-	return s.SocketDataBuffer.BufferData()[s.From:s.Size]
-}
-
-func (s *SocketDataEventLimited) BufferLen() int {
-	return s.Size - s.From
-}
-
-func (s *SocketDataEventLimited) BufferStartPosition() int {
-	return s.From
-}
-
-type SocketDetailEvent struct {
-	ConnectionID     uint64
-	RandomID         uint64
-	DataID           uint64
-	TotalPackageSize uint64
-	IfIndex          uint32
-	PackageCount     uint8
-	FuncName         SocketFunctionName
-	RTTCount         uint8
-	Protocol         ConnectionProtocol
-	RTTTime          uint32
-}
-
-func (s *SocketDetailEvent) GenerateConnectionID() string {
-	return fmt.Sprintf("%d_%d", s.ConnectionID, s.RandomID)
-}
diff --git a/pkg/accesslog/events/detail.go b/pkg/accesslog/events/detail.go
new file mode 100644
index 0000000..ecb5f11
--- /dev/null
+++ b/pkg/accesslog/events/detail.go
@@ -0,0 +1,73 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package events
+
+import (
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/host"
+)
+
+type SocketDetailEvent struct {
+	ConnectionID uint64
+	RandomID     uint64
+	DataID0      uint64
+
+	StartTime uint64
+	EndTime   uint64
+
+	L4Duration                    uint32
+	L3Duration                    uint32
+	L3LocalDuration               uint32
+	L3OutputDuration              uint32
+	L3ResolveMacDuration          uint32
+	L3NetFilterDuration           uint32
+	L2Duration                    uint32
+	L2ReadySendDuration           uint32
+	L2SendDuration                uint32
+	L2PackageToQueueDuration      uint32
+	L3TotalRcvDuration            uint32
+	IfIndex                       uint32
+	L4PackageRcvFromQueueDuration uint64
+	L4TotalPackageSize            uint64
+	L2EnterQueueCount             uint8
+	L4PackageCount                uint8
+	L4RetransmitPackageCount      uint8
+	L3ResolveMacCount             uint8
+	L3NetFilterCount              uint8
+	FunctionName                  enums.SocketFunctionName
+	Protocol                      enums.ConnectionProtocol
+	SSL                           uint8
+}
+
+func (d *SocketDetailEvent) GetConnectionID() uint64 {
+	return d.ConnectionID
+}
+
+func (d *SocketDetailEvent) GetRandomID() uint64 {
+	return d.RandomID
+}
+
+func (d *SocketDetailEvent) Timestamp() time.Time {
+	return host.Time(d.StartTime)
+}
+
+func (d *SocketDetailEvent) DataID() uint64 {
+	return d.DataID0
+}
diff --git a/pkg/tools/host/network.go b/pkg/accesslog/forwarder/close.go
similarity index 50%
copy from pkg/tools/host/network.go
copy to pkg/accesslog/forwarder/close.go
index 34f24de..239c18d 100644
--- a/pkg/tools/host/network.go
+++ b/pkg/accesslog/forwarder/close.go
@@ -15,48 +15,32 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package host
+package forwarder
 
 import (
-	"net"
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
 
-	"github.com/apache/skywalking-rover/pkg/logger"
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
 )
 
-var interfaces map[int]*net.Interface
-var log = logger.GetLogger("tools", "host")
-
 func init() {
-	if err := refreshInterfaces(); err != nil {
-		panic(err)
-	}
+	registerKernelLogBuilder(common.LogTypeClose, closeLogBuilder)
 }
 
-func NetworkName(ifindex int) string {
-	i := interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	if e := refreshInterfaces(); e != nil {
-		log.Warnf("error to refresh interfaces: %v", e)
-		return ""
-	}
-	i = interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	return ""
+func SendCloseEvent(context *common.AccessLogContext, event *common.CloseEventWithNotify) {
+	context.Queue.AppendKernelLog(common.LogTypeClose, event)
 }
 
-func refreshInterfaces() error {
-	results, err := net.Interfaces()
-	if err != nil {
-		return err
-	}
-	tmp := make(map[int]*net.Interface)
-	for _, interf := range results {
-		tmp[interf.Index] = &interf
+func closeLogBuilder(event events.Event) *v3.AccessLogKernelLog {
+	closeEvent := event.(*common.CloseEventWithNotify)
+	closeOp := &v3.AccessLogKernelCloseOperation{}
+	closeOp.StartTime = BuildOffsetTimestamp(closeEvent.StartTime)
+	closeOp.EndTime = BuildOffsetTimestamp(closeEvent.EndTime)
+	closeOp.Success = closeEvent.Success == 1
+	return &v3.AccessLogKernelLog{
+		Operation: &v3.AccessLogKernelLog_Close{
+			Close: closeOp,
+		},
 	}
-	interfaces = tmp
-	return nil
 }
diff --git a/pkg/accesslog/forwarder/connect.go b/pkg/accesslog/forwarder/connect.go
new file mode 100644
index 0000000..e57ac4e
--- /dev/null
+++ b/pkg/accesslog/forwarder/connect.go
@@ -0,0 +1,64 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package forwarder
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/ip"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+func init() {
+	registerKernelLogBuilder(common.LogTypeConnect, connectLogBuilder)
+}
+
+func SendConnectEvent(context *common.AccessLogContext, event *events.SocketConnectEvent, socketPair *ip.SocketPair) {
+	context.Queue.AppendKernelLog(common.LogTypeConnect, &common.ConnectEventWithSocket{
+		SocketConnectEvent: event,
+		SocketPair:         socketPair,
+	})
+}
+
+func connectLogBuilder(event events.Event) *v3.AccessLogKernelLog {
+	connectEvent := event.(*common.ConnectEventWithSocket)
+	switch connectEvent.FuncName {
+	case enums.SocketFunctionNameConnect:
+		return &v3.AccessLogKernelLog{
+			Operation: &v3.AccessLogKernelLog_Connect{
+				Connect: &v3.AccessLogKernelConnectOperation{
+					StartTime: BuildOffsetTimestamp(connectEvent.StartTime),
+					EndTime:   BuildOffsetTimestamp(connectEvent.EndTime),
+					Success:   connectEvent.ConnectSuccess == 1,
+				},
+			},
+		}
+	case enums.SocketFunctionNameAccept:
+		return &v3.AccessLogKernelLog{
+			Operation: &v3.AccessLogKernelLog_Accept{
+				Accept: &v3.AccessLogKernelAcceptOperation{
+					StartTime: BuildOffsetTimestamp(connectEvent.StartTime),
+					EndTime:   BuildOffsetTimestamp(connectEvent.EndTime),
+				},
+			},
+		}
+	}
+	return nil
+}
diff --git a/pkg/tools/host/network.go b/pkg/accesslog/forwarder/forwarder.go
similarity index 51%
copy from pkg/tools/host/network.go
copy to pkg/accesslog/forwarder/forwarder.go
index 34f24de..3cac342 100644
--- a/pkg/tools/host/network.go
+++ b/pkg/accesslog/forwarder/forwarder.go
@@ -15,48 +15,37 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package host
+package forwarder
 
 import (
-	"net"
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
 
-	"github.com/apache/skywalking-rover/pkg/logger"
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
 )
 
-var interfaces map[int]*net.Interface
-var log = logger.GetLogger("tools", "host")
+type KernelLogBuilder func(data events.Event) *v3.AccessLogKernelLog
 
-func init() {
-	if err := refreshInterfaces(); err != nil {
-		panic(err)
-	}
+var kernelLogBuilders = make([]KernelLogBuilder, 10)
+
+func registerKernelLogBuilder(tp common.LogType, builder KernelLogBuilder) {
+	kernelLogBuilders[tp] = builder
 }
 
-func NetworkName(ifindex int) string {
-	i := interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	if e := refreshInterfaces(); e != nil {
-		log.Warnf("error to refresh interfaces: %v", e)
-		return ""
+func BuildKernelLogFromEvent(tp common.LogType, event events.Event) *v3.AccessLogKernelLog {
+	builder := kernelLogBuilders[tp]
+	if builder == nil {
+		return nil
 	}
-	i = interfaces[ifindex]
-	if i != nil {
-		return i.Name
-	}
-	return ""
+	return builder(event)
 }
 
-func refreshInterfaces() error {
-	results, err := net.Interfaces()
-	if err != nil {
-		return err
-	}
-	tmp := make(map[int]*net.Interface)
-	for _, interf := range results {
-		tmp[interf.Index] = &interf
+func BuildOffsetTimestamp(t uint64) *v3.EBPFTimestamp {
+	return &v3.EBPFTimestamp{
+		Timestamp: &v3.EBPFTimestamp_Offset{
+			Offset: &v3.EBPFOffsetTimestamp{
+				Offset: t,
+			},
+		},
 	}
-	interfaces = tmp
-	return nil
 }
diff --git a/pkg/profiling/task/network/analyze/enums/protocol.go b/pkg/accesslog/forwarder/protocol.go
similarity index 66%
copy from pkg/profiling/task/network/analyze/enums/protocol.go
copy to pkg/accesslog/forwarder/protocol.go
index 555705c..dd158c8 100644
--- a/pkg/profiling/task/network/analyze/enums/protocol.go
+++ b/pkg/accesslog/forwarder/protocol.go
@@ -15,11 +15,15 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package enums
+package forwarder
 
-type ParseResult int
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
 
-const (
-	ParseResultSuccess ParseResult = iota
-	ParseResultSkipPackage
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
 )
+
+func SendTransferProtocolEvent(context *common.AccessLogContext, kernelLogs []*events.SocketDetailEvent, protocolData *v3.AccessLogProtocolLogs) {
+	context.Queue.AppendProtocolLog(kernelLogs, protocolData)
+}
diff --git a/pkg/accesslog/forwarder/transfer.go b/pkg/accesslog/forwarder/transfer.go
new file mode 100644
index 0000000..882da0c
--- /dev/null
+++ b/pkg/accesslog/forwarder/transfer.go
@@ -0,0 +1,141 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package forwarder
+
+import (
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+func init() {
+	registerKernelLogBuilder(common.LogTypeKernelTransfer, kernelTransferLogBuilder)
+}
+
+func SendTransferNoProtocolEvent(context *common.AccessLogContext, event *events.SocketDetailEvent) {
+	context.Queue.AppendKernelLog(common.LogTypeKernelTransfer, event)
+}
+
+func kernelTransferLogBuilder(event events.Event) *v3.AccessLogKernelLog {
+	transferEvent := event.(*events.SocketDetailEvent)
+	// process the read or write
+	switch transferEvent.FunctionName.GetSocketOperationType() {
+	case enums.SocketOperationTypeWrite:
+		return &v3.AccessLogKernelLog{
+			Operation: &v3.AccessLogKernelLog_Write{
+				Write: &v3.AccessLogKernelWriteOperation{
+					StartTime: BuildOffsetTimestamp(transferEvent.StartTime),
+					EndTime:   BuildOffsetTimestamp(transferEvent.EndTime),
+					Syscall:   parseWriteSyscall(transferEvent.FunctionName),
+					L4Metrics: &v3.AccessLogKernelWriteL4Metrics{
+						TotalDuration:               uint64(transferEvent.L4Duration),
+						TotalTransmitPackageCount:   int64(transferEvent.L4PackageCount),
+						TotalRetransmitPackageCount: int64(transferEvent.L4RetransmitPackageCount),
+						TotalPackageSize:            int64(transferEvent.L4TotalPackageSize),
+					},
+					L3Metrics: &v3.AccessLogKernelWriteL3Metrics{
+						TotalDuration:           uint64(transferEvent.L3Duration),
+						TotalLocalDuration:      uint64(transferEvent.L3LocalDuration),
+						TotalOutputDuration:     uint64(transferEvent.L3OutputDuration),
+						TotalResolveMACCount:    uint64(transferEvent.L3ResolveMacCount),
+						TotalResolveMACDuration: uint64(transferEvent.L3ResolveMacDuration),
+						TotalNetFilterCount:     uint64(transferEvent.L3NetFilterCount),
+						TotalNetFilterDuration:  uint64(transferEvent.L3NetFilterDuration),
+					},
+					L2Metrics: &v3.AccessLogKernelWriteL2Metrics{
+						TotalDuration:              uint64(transferEvent.L2Duration),
+						Ifindex:                    transferEvent.IfIndex,
+						TotalEnterQueueBufferCount: uint64(transferEvent.L2EnterQueueCount),
+						TotalReadySendDuration:     uint64(transferEvent.L2ReadySendDuration),
+						TotalNetDeviceSendDuration: uint64(transferEvent.L2SendDuration),
+					},
+				},
+			},
+		}
+	case enums.SocketOperationTypeRead:
+		return &v3.AccessLogKernelLog{
+			Operation: &v3.AccessLogKernelLog_Read{
+				Read: &v3.AccessLogKernelReadOperation{
+					StartTime: BuildOffsetTimestamp(transferEvent.StartTime),
+					EndTime:   BuildOffsetTimestamp(transferEvent.EndTime),
+					Syscall:   parseReadSyscall(transferEvent.FunctionName),
+					L2Metrics: &v3.AccessLogKernelReadL2Metrics{
+						Ifindex:                          transferEvent.IfIndex,
+						TotalPackageCount:                uint32(transferEvent.L4PackageCount),
+						TotalPackageSize:                 transferEvent.L4TotalPackageSize,
+						TotalPackageToQueueDuration:      uint64(transferEvent.L2PackageToQueueDuration),
+						TotalRcvPackageFromQueueDuration: transferEvent.L4PackageRcvFromQueueDuration,
+					},
+					L3Metrics: &v3.AccessLogKernelReadL3Metrics{
+						TotalDuration:          uint64(transferEvent.L3Duration),
+						TotalRecvDuration:      uint64(transferEvent.L3TotalRcvDuration),
+						TotalLocalDuration:     uint64(transferEvent.L3LocalDuration),
+						TotalNetFilterCount:    uint64(transferEvent.L3NetFilterCount),
+						TotalNetFilterDuration: uint64(transferEvent.L3NetFilterDuration),
+					},
+					L4Metrics: &v3.AccessLogKernelReadL4Metrics{
+						TotalDuration: uint64(transferEvent.L4Duration),
+					},
+				},
+			},
+		}
+	}
+	return nil
+}
+
+func parseReadSyscall(funcName enums.SocketFunctionName) v3.AccessLogKernelReadSyscall {
+	switch funcName {
+	case enums.SocketFunctionNameRead:
+		return v3.AccessLogKernelReadSyscall_Read
+	case enums.SocketFunctionNameReadv:
+		return v3.AccessLogKernelReadSyscall_Readv
+	case enums.SocketFunctionNameRecv:
+		return v3.AccessLogKernelReadSyscall_Recv
+	case enums.SocketFunctionNameRecvfrom:
+		return v3.AccessLogKernelReadSyscall_RecvFrom
+	case enums.SocketFunctionNameRecvMsg:
+		return v3.AccessLogKernelReadSyscall_RecvMsg
+	case enums.SocketFunctionNameRecvMMsg:
+		return v3.AccessLogKernelReadSyscall_RecvMmsg
+	default:
+		return v3.AccessLogKernelReadSyscall_Read
+	}
+}
+
+func parseWriteSyscall(funcName enums.SocketFunctionName) v3.AccessLogKernelWriteSyscall {
+	switch funcName {
+	case enums.SocketFunctionNameSend:
+		return v3.AccessLogKernelWriteSyscall_Send
+	case enums.SocketFunctionNameSendto:
+		return v3.AccessLogKernelWriteSyscall_SendTo
+	case enums.SocketFunctionNameSendMsg:
+		return v3.AccessLogKernelWriteSyscall_SendMsg
+	case enums.SocketFunctionNameSendMMSg:
+		return v3.AccessLogKernelWriteSyscall_SendMmsg
+	case enums.SocketFunctionNameSendFile:
+		return v3.AccessLogKernelWriteSyscall_SendFile
+	case enums.SocketFunctionNameWrite:
+		return v3.AccessLogKernelWriteSyscall_Write
+	case enums.SocketFunctionNameWritev:
+		return v3.AccessLogKernelWriteSyscall_Writev
+	default:
+		return v3.AccessLogKernelWriteSyscall_Write
+	}
+}
diff --git a/pkg/process/module.go b/pkg/accesslog/module.go
similarity index 53%
copy from pkg/process/module.go
copy to pkg/accesslog/module.go
index 769880e..ce1b03c 100644
--- a/pkg/process/module.go
+++ b/pkg/accesslog/module.go
@@ -15,28 +15,27 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package process
+package accesslog
 
 import (
 	"context"
-	"time"
 
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
 	"github.com/apache/skywalking-rover/pkg/core"
 	"github.com/apache/skywalking-rover/pkg/module"
-	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/process/finders"
+	"github.com/apache/skywalking-rover/pkg/process"
 )
 
-const ModuleName = "process_discovery"
+const ModuleName = "access_log"
 
 type Module struct {
-	config *Config
+	config *common.Config
 
-	manager *finders.ProcessManager
+	runner *Runner
 }
 
 func NewModule() *Module {
-	return &Module{config: &Config{}}
+	return &Module{config: &common.Config{}}
 }
 
 func (m *Module) Name() string {
@@ -44,7 +43,7 @@ func (m *Module) Name() string {
 }
 
 func (m *Module) RequiredModules() []string {
-	return []string{core.ModuleName}
+	return []string{core.ModuleName, process.ModuleName}
 }
 
 func (m *Module) Config() module.ConfigInterface {
@@ -52,49 +51,24 @@ func (m *Module) Config() module.ConfigInterface {
 }
 
 func (m *Module) Start(ctx context.Context, mgr *module.Manager) error {
-	period, err := time.ParseDuration(m.config.HeartbeatPeriod)
+	runner, err := NewRunner(mgr, m.config)
 	if err != nil {
 		return err
 	}
-	processManager, err := finders.NewProcessManager(ctx, mgr, period, m.config.PropertiesReportPeriod,
-		m.config.Scanner, m.config.Kubernetes)
+	err = runner.Start(ctx)
 	if err != nil {
 		return err
 	}
-	m.manager = processManager
-
+	m.runner = runner
 	return nil
 }
 
 func (m *Module) NotifyStartSuccess() {
-	// notify all finder to report processes
-	m.manager.Start()
 }
 
 func (m *Module) Shutdown(ctx context.Context, mgr *module.Manager) error {
-	return m.manager.Shutdown()
-}
-
-func (m *Module) GetAllProcesses() []api.ProcessInterface {
-	return m.manager.GetAllProcesses()
-}
-
-func (m *Module) FindProcessByID(processID string) api.ProcessInterface {
-	return m.manager.FindProcessByID(processID)
-}
-
-func (m *Module) FindAllRegisteredProcesses() []api.ProcessInterface {
-	return m.manager.FindAllRegisteredProcesses()
-}
-
-func (m *Module) FindProcessByPID(pid int32) []api.ProcessInterface {
-	return m.manager.FindProcessByPID(pid)
-}
-
-func (m *Module) AddListener(listener api.ProcessListener) {
-	m.manager.AddListener(listener)
-}
-
-func (m *Module) DeleteListener(listener api.ProcessListener) {
-	m.manager.DeleteListener(listener)
+	if m.runner != nil {
+		return m.runner.Stop()
+	}
+	return nil
 }
diff --git a/pkg/accesslog/runner.go b/pkg/accesslog/runner.go
new file mode 100644
index 0000000..0571b4a
--- /dev/null
+++ b/pkg/accesslog/runner.go
@@ -0,0 +1,321 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package accesslog
+
+import (
+	"context"
+	"fmt"
+	"time"
+
+	"github.com/apache/skywalking-rover/pkg/accesslog/bpf"
+	"github.com/apache/skywalking-rover/pkg/accesslog/collector"
+	"github.com/apache/skywalking-rover/pkg/accesslog/common"
+	"github.com/apache/skywalking-rover/pkg/accesslog/events"
+	"github.com/apache/skywalking-rover/pkg/accesslog/forwarder"
+	"github.com/apache/skywalking-rover/pkg/core"
+	"github.com/apache/skywalking-rover/pkg/core/backend"
+	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/module"
+	"github.com/apache/skywalking-rover/pkg/process"
+	"github.com/apache/skywalking-rover/pkg/tools/host"
+
+	v32 "skywalking.apache.org/repo/goapi/collect/common/v3"
+	v3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
+)
+
+const kernelAccessLogCacheTime = time.Minute * 5
+
+var log = logger.GetLogger("access_log", "runner")
+
+type Runner struct {
+	context    *common.AccessLogContext
+	collectors []collector.Collector
+	mgr        *module.Manager
+	backendOp  backend.Operator
+	alsClient  v3.EBPFAccessLogServiceClient
+	ctx        context.Context
+}
+
+func NewRunner(mgr *module.Manager, config *common.Config) (*Runner, error) {
+	bpfLoader, err := bpf.NewLoader()
+	if err != nil {
+		return nil, err
+	}
+	flushDuration, err := time.ParseDuration(config.Flush.Period)
+	if err != nil {
+		return nil, fmt.Errorf("parse flush period error: %v", err)
+	}
+	backendOP := mgr.FindModule(core.ModuleName).(core.Operator).BackendOperator()
+	runner := &Runner{
+		context: &common.AccessLogContext{
+			BPF:           bpfLoader,
+			Config:        config,
+			ConnectionMgr: common.NewConnectionManager(mgr, bpfLoader),
+		},
+		collectors: collector.Collectors(),
+		mgr:        mgr,
+		backendOp:  backendOP,
+		alsClient:  v3.NewEBPFAccessLogServiceClient(backendOP.GetConnection()),
+	}
+	runner.context.Queue = common.NewQueue(config.Flush.MaxCountOneStream, flushDuration, runner)
+	return runner, nil
+}
+
+func (r *Runner) Start(ctx context.Context) error {
+	r.ctx = ctx
+	r.context.RuntimeContext = ctx
+	r.context.Queue.Start(ctx)
+	r.context.ConnectionMgr.Start()
+	for _, c := range r.collectors {
+		err := c.Start(r.mgr, r.context)
+		if err != nil {
+			return err
+		}
+	}
+
+	if err := r.context.BPF.HasError(); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (r *Runner) Consume(kernels chan *common.KernelLog, protocols chan *common.ProtocolLog) {
+	if r.backendOp.GetConnectionStatus() != backend.Connected {
+		log.Warnf("failure to connect to the backend, skip generating access log")
+		return
+	}
+
+	allLogs := r.buildConnectionLogs(kernels, protocols)
+	log.Debugf("ready to send access log, connection count: %d", len(allLogs))
+	if len(allLogs) == 0 {
+		return
+	}
+	if err := r.sendLogs(allLogs); err != nil {
+		log.Warnf("send access log failure: %v", err)
+	}
+}
+
+func (r *Runner) buildConnectionLogs(kernels chan *common.KernelLog, protocols chan *common.ProtocolLog) map[*common.ConnectionInfo]*connectionLogs {
+	result := make(map[*common.ConnectionInfo]*connectionLogs)
+	r.buildKernelLogs(kernels, result)
+	r.buildProtocolLogs(protocols, result)
+
+	r.context.ConnectionMgr.OnBuildConnectionLogFinished()
+	return result
+}
+
+func (r *Runner) buildKernelLogs(kernels chan *common.KernelLog, result map[*common.ConnectionInfo]*connectionLogs) {
+	delayAppends := make([]*common.KernelLog, 0)
+	for {
+		select {
+		case kernelLog := <-kernels:
+			connection, curLog, delay := r.buildKernelLog(kernelLog)
+			if connection != nil && curLog != nil {
+				logs, exist := result[connection]
+				if !exist {
+					logs = newConnectionLogs()
+					result[connection] = logs
+				}
+
+				logs.kernels = append(logs.kernels, curLog)
+			} else if delay {
+				delayAppends = append(delayAppends, kernelLog)
+			}
+		default:
+			for _, delayAppend := range delayAppends {
+				kernels <- delayAppend
+			}
+			return
+		}
+	}
+}
+
+func (r *Runner) buildProtocolLogs(protocols chan *common.ProtocolLog, result map[*common.ConnectionInfo]*connectionLogs) {
+	delayAppends := make([]*common.ProtocolLog, 0)
+	for {
+		select {
+		case protocolLog := <-protocols:
+			connection, kernelLogs, protocolLogs, delay := r.buildProtocolLog(protocolLog)
+			if connection != nil && len(kernelLogs) > 0 && protocolLogs != nil {
+				logs, exist := result[connection]
+				if !exist {
+					logs = newConnectionLogs()
+					result[connection] = logs
+				}
+				logs.protocols = append(logs.protocols, &connectionProtocolLog{
+					kernels:  kernelLogs,
+					protocol: protocolLogs,
+				})
+			} else if delay {
+				delayAppends = append(delayAppends, protocolLog)
+			}
+		default:
+			for _, delayAppend := range delayAppends {
+				protocols <- delayAppend
+			}
+			return
+		}
+	}
+}
+
+func (r *Runner) sendLogs(allLogs map[*common.ConnectionInfo]*connectionLogs) error {
+	streaming, err := r.alsClient.Collect(r.ctx)
+	if err != nil {
+		return err
+	}
+
+	firstLog := true
+	firstConnection := true
+	for connection, logs := range allLogs {
+		if len(logs.kernels) > 0 {
+			r.sendLogToTheStream(streaming, r.buildAccessLogMessage(firstLog, firstConnection, connection, logs.kernels, nil))
+			firstLog, firstConnection = false, false
+		}
+		for _, protocolLog := range logs.protocols {
+			r.sendLogToTheStream(streaming, r.buildAccessLogMessage(firstLog, firstConnection, connection, protocolLog.kernels, protocolLog.protocol))
+			firstLog, firstConnection = false, false
+		}
+
+		firstConnection = true
+	}
+
+	if _, err := streaming.CloseAndRecv(); err != nil {
+		log.Warnf("closing the access log streaming error: %v", err)
+	}
+	return nil
+}
+
+func (r *Runner) sendLogToTheStream(streaming v3.EBPFAccessLogService_CollectClient, logMsg *v3.EBPFAccessLogMessage) {
+	if err := streaming.Send(logMsg); err != nil {
+		log.Warnf("send access log failure: %v", err)
+	}
+}
+
+func (r *Runner) buildAccessLogMessage(firstLog, firstConnection bool, conn *common.ConnectionInfo,
+	kernelLogs []*v3.AccessLogKernelLog, protocolLog *v3.AccessLogProtocolLogs) *v3.EBPFAccessLogMessage {
+	var rpcCon *v3.AccessLogConnection
+	if firstConnection {
+		rpcCon = conn.RPCConnection
+	}
+	return &v3.EBPFAccessLogMessage{
+		Node:        r.BuildNodeInfo(firstLog),
+		Connection:  rpcCon,
+		KernelLogs:  kernelLogs,
+		ProtocolLog: protocolLog,
+	}
+}
+
+func (r *Runner) BuildNodeInfo(needs bool) *v3.EBPFAccessLogNodeInfo {
+	if !needs {
+		return nil
+	}
+	netInterfaces := make([]*v3.EBPFAccessLogNodeNetInterface, 0)
+	for i, n := range host.AllNetworkInterfaces() {
+		netInterfaces = append(netInterfaces, &v3.EBPFAccessLogNodeNetInterface{
+			Index: int32(i),
+			Mtu:   int32(n.MTU),
+			Name:  n.Name,
+		})
+	}
+	return &v3.EBPFAccessLogNodeInfo{
+		Name:          r.mgr.FindModule(process.ModuleName).(process.K8sOperator).NodeName(),
+		NetInterfaces: netInterfaces,
+		BootTime:      r.convertTimeToInstant(host.BootTime),
+	}
+}
+
+func (r *Runner) convertTimeToInstant(t time.Time) *v32.Instant {
+	return &v32.Instant{
+		Seconds: t.Unix(),
+		Nanos:   int32(t.Nanosecond()),
+	}
+}
+
+func (r *Runner) buildProtocolLog(protocolLog *common.ProtocolLog) (*common.ConnectionInfo,
+	[]*v3.AccessLogKernelLog, *v3.AccessLogProtocolLogs, bool) {
+	if len(protocolLog.KernelLogs) == 0 {
+		return nil, nil, nil, false
+	}
+	firstKernelLog := protocolLog.KernelLogs[0]
+	pid, _ := events.ParseConnectionID(firstKernelLog.GetConnectionID())
+	// if the process not monitoring, then ignore it
+	if !r.context.ConnectionMgr.ProcessIsMonitor(pid) {
+		return nil, nil, nil, false
+	}
+	connection := r.context.ConnectionMgr.Find(firstKernelLog)
+	if connection == nil {
+		// if the connection cannot be found, it means that the connection have not been established
+		// just re-add into the queue for checking in the next period
+		if time.Since(firstKernelLog.Timestamp()) > kernelAccessLogCacheTime {
+			return nil, nil, nil, false
+		}
+		return nil, nil, nil, true
+	}
+	kernelLogs := make([]*v3.AccessLogKernelLog, 0)
+	for _, kl := range protocolLog.KernelLogs {
+		event := forwarder.BuildKernelLogFromEvent(common.LogTypeKernelTransfer, kl)
+		if event == nil {
+			continue
+		}
+		kernelLogs = append(kernelLogs, event)
+	}
+
+	return connection, kernelLogs, protocolLog.Protocol, false
+}
+
+func (r *Runner) buildKernelLog(kernelLog *common.KernelLog) (*common.ConnectionInfo, *v3.AccessLogKernelLog, bool) {
+	pid, _ := events.ParseConnectionID(kernelLog.Event.GetConnectionID())
+	// if the process not monitoring, then ignore it
+	if !r.context.ConnectionMgr.ProcessIsMonitor(pid) {
+		return nil, nil, false
+	}
+	connection := r.context.ConnectionMgr.Find(kernelLog.Event)
+	if connection == nil {
+		// if the connection cannot be found, it means that the connection have not been established
+		// just re-add into the queue for checking in the next period
+		if time.Since(kernelLog.Event.Timestamp()) > kernelAccessLogCacheTime {
+			return nil, nil, false
+		}
+		return nil, nil, true
+	}
+	event := forwarder.BuildKernelLogFromEvent(kernelLog.Type, kernelLog.Event)
+	return connection, event, false
+}
+
+func (r *Runner) Stop() error {
+	r.context.ConnectionMgr.Stop()
+	return nil
+}
+
+type connectionLogs struct {
+	kernels   []*v3.AccessLogKernelLog
+	protocols []*connectionProtocolLog
+}
+
+type connectionProtocolLog struct {
+	kernels  []*v3.AccessLogKernelLog
+	protocol *v3.AccessLogProtocolLogs
+}
+
+func newConnectionLogs() *connectionLogs {
+	return &connectionLogs{
+		kernels:   make([]*v3.AccessLogKernelLog, 0),
+		protocols: make([]*connectionProtocolLog, 0),
+	}
+}
diff --git a/pkg/boot/register.go b/pkg/boot/register.go
index 8f0d64d..f383c90 100644
--- a/pkg/boot/register.go
+++ b/pkg/boot/register.go
@@ -18,6 +18,7 @@
 package boot
 
 import (
+	"github.com/apache/skywalking-rover/pkg/accesslog"
 	"github.com/apache/skywalking-rover/pkg/core"
 	"github.com/apache/skywalking-rover/pkg/logger"
 	"github.com/apache/skywalking-rover/pkg/module"
@@ -31,4 +32,5 @@ func init() {
 	module.Register(core.NewModule())
 	module.Register(process.NewModule())
 	module.Register(profiling.NewModule())
+	module.Register(accesslog.NewModule())
 }
diff --git a/pkg/process/api.go b/pkg/process/api.go
index 9f7bdb3..b84453b 100644
--- a/pkg/process/api.go
+++ b/pkg/process/api.go
@@ -30,4 +30,11 @@ type Operator interface {
 	AddListener(listener api.ProcessListener)
 	// DeleteListener delete the process listener
 	DeleteListener(listener api.ProcessListener)
+	// ShouldMonitor check the process should be monitored
+	ShouldMonitor(pid int32) bool
+}
+
+type K8sOperator interface {
+	// NodeName get the node name
+	NodeName() string
 }
diff --git a/pkg/process/api/process.go b/pkg/process/api/process.go
index fca705e..ad77644 100644
--- a/pkg/process/api/process.go
+++ b/pkg/process/api/process.go
@@ -58,11 +58,33 @@ type ProcessInterface interface {
 	ExeName() (string, error)
 	// OriginalProcess from process library
 	OriginalProcess() *process.Process
+	// DetectProcess from finder
+	DetectProcess() DetectedProcess
 
 	// PortIsExpose check the port is exposed
 	PortIsExpose(port int) bool
 	// DetectNewExposePort add a new detected expose port
 	DetectNewExposePort(port int)
+	// ExposeHosts get all exposed hosts
+	ExposeHosts() []string
+}
+
+// DetectedProcess from the finder
+type DetectedProcess interface {
+	// Pid of process in host
+	Pid() int32
+	// OriginalProcess is works for query the process data
+	OriginalProcess() *process.Process
+	// Entity of process, is related with backend entity
+	Entity() *ProcessEntity
+	// DetectType define the process find type
+	DetectType() ProcessDetectType
+	// ProfilingStat of process
+	ProfilingStat() *profiling.Info
+	// ExposePorts define which ports are exposed
+	ExposePorts() []int
+	// ExposeHosts define which hosts are exposed
+	ExposeHosts() []string
 }
 
 // ProcessEntity is related to backend entity concept
diff --git a/pkg/process/finders/base/finder.go b/pkg/process/finders/base/finder.go
index d1edefa..d4ba8b1 100644
--- a/pkg/process/finders/base/finder.go
+++ b/pkg/process/finders/base/finder.go
@@ -42,20 +42,25 @@ type ProcessFinder interface {
 	// DetectType of Process is detecting
 	DetectType() api.ProcessDetectType
 
+	// ShouldMonitor validate the process needs to be monitored, if true, then add it into the storage
+	ShouldMonitor(pid int32) bool
+
 	// ValidateProcessIsSame between two same finder process
-	ValidateProcessIsSame(p1, p2 DetectedProcess) bool
+	ValidateProcessIsSame(p1, p2 api.DetectedProcess) bool
 
 	// BuildEBPFProcess is transform the process entity as backend protocol data
-	BuildEBPFProcess(ctx *BuildEBPFProcessContext, process DetectedProcess) *v3.EBPFProcessProperties
+	BuildEBPFProcess(ctx *BuildEBPFProcessContext, process api.DetectedProcess) *v3.EBPFProcessProperties
 	// BuildNecessaryProperties is getting minimize necessary properties when keep alive
-	BuildNecessaryProperties(process DetectedProcess) []*commonv3.KeyStringValuePair
+	BuildNecessaryProperties(process api.DetectedProcess) []*commonv3.KeyStringValuePair
 	// ParseProcessId is means how to read the process id receive from backend
-	ParseProcessID(process DetectedProcess, downstream *v3.EBPFProcessDownstream) string
+	ParseProcessID(process api.DetectedProcess, downstream *v3.EBPFProcessDownstream) string
 }
 
 // ProcessManager is an API work for help ProcessFinder synchronized process with backend
 type ProcessManager interface {
 	GetModuleManager() *module.Manager
 	// SyncAllProcessInFinder is mean synchronized all processes data from current ProcessFinder
-	SyncAllProcessInFinder(processes []DetectedProcess)
+	SyncAllProcessInFinder(processes []api.DetectedProcess)
+	// AddDetectedProcess only add the specific processes
+	AddDetectedProcess(processes []api.DetectedProcess)
 }
diff --git a/pkg/process/finders/context.go b/pkg/process/finders/context.go
index b1760a4..1ed5cad 100644
--- a/pkg/process/finders/context.go
+++ b/pkg/process/finders/context.go
@@ -19,7 +19,6 @@ package finders
 
 import (
 	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/process/finders/base"
 	"github.com/apache/skywalking-rover/pkg/tools/profiling"
 
 	"github.com/shirou/gopsutil/process"
@@ -45,7 +44,7 @@ type ProcessContext struct {
 	syncStatus ProcessUploadStatus
 
 	// detectProcess from finder
-	detectProcess base.DetectedProcess
+	detectProcess api.DetectedProcess
 	detectType    api.ProcessDetectType
 
 	// cache
@@ -73,6 +72,10 @@ func (p *ProcessContext) ProfilingStat() *profiling.Info {
 	return p.detectProcess.ProfilingStat()
 }
 
+func (p *ProcessContext) DetectProcess() api.DetectedProcess {
+	return p.detectProcess
+}
+
 func (p *ProcessContext) ExeName() (string, error) {
 	if p.exeName == "" {
 		exe, err := p.detectProcess.OriginalProcess().Name()
@@ -95,3 +98,7 @@ func (p *ProcessContext) PortIsExpose(port int) bool {
 func (p *ProcessContext) DetectNewExposePort(port int) {
 	p.exposedPorts[port] = true
 }
+
+func (p *ProcessContext) ExposeHosts() []string {
+	return p.detectProcess.ExposeHosts()
+}
diff --git a/pkg/process/finders/kubernetes/finder.go b/pkg/process/finders/kubernetes/finder.go
index c39ff75..14522d6 100644
--- a/pkg/process/finders/kubernetes/finder.go
+++ b/pkg/process/finders/kubernetes/finder.go
@@ -155,54 +155,60 @@ func (f *ProcessFinder) analyzeProcesses() error {
 		return err
 	}
 
-	result := make([]base.DetectedProcess, 0)
+	result := make([]api.DetectedProcess, 0)
 	for _, p := range processes {
-		createTime, err := p.CreateTime()
-		if err != nil {
-			continue
-		}
-		processCahceKey := fmt.Sprintf("%d_%d", p.Pid, createTime)
-		cachedProcesses, exist := f.processCache.Get(processCahceKey)
-		if exist {
-			for _, pro := range cachedProcesses.([]*Process) {
-				result = append(result, pro)
-			}
-			continue
-		}
+		result, _ = f.buildProcess(p, result, containers)
+	}
 
-		cgroups, err := f.getProcessCGroup(p.Pid)
-		if err != nil {
-			continue
-		}
+	if len(result) > 0 {
+		f.manager.SyncAllProcessInFinder(result)
+	}
+	return nil
+}
 
-		var c *PodContainer
-		for _, cgroup := range cgroups {
-			if cc := containers[cgroup]; cc != nil {
-				c = cc
-				break
-			}
-		}
-		if c == nil {
-			continue
+func (f *ProcessFinder) buildProcess(p *process.Process, detectedProcesses []api.DetectedProcess,
+	containers map[string]*PodContainer) ([]api.DetectedProcess, bool) {
+	createTime, err := p.CreateTime()
+	if err != nil {
+		return detectedProcesses, false
+	}
+	processCahceKey := fmt.Sprintf("%d_%d", p.Pid, createTime)
+	cachedProcesses, exist := f.processCache.Get(processCahceKey)
+	if exist {
+		for _, pro := range cachedProcesses.([]*Process) {
+			detectedProcesses = append(detectedProcesses, pro)
 		}
+		return detectedProcesses, false
+	}
 
-		// find process builder
-		ps, err := f.buildProcesses(p, c)
-		if err != nil {
-			log.Warnf("find process builder error for pid: %d, err: %v", p.Pid, err)
-			continue
-		}
+	cgroups, err := f.getProcessCGroup(p.Pid)
+	if err != nil {
+		return detectedProcesses, false
+	}
 
-		for _, pro := range ps {
-			result = append(result, pro)
+	var c *PodContainer
+	for _, cgroup := range cgroups {
+		if cc := containers[cgroup]; cc != nil {
+			c = cc
+			break
 		}
-		f.processCache.Add(processCahceKey, ps)
+	}
+	if c == nil {
+		return detectedProcesses, false
 	}
 
-	if len(result) > 0 {
-		f.manager.SyncAllProcessInFinder(result)
+	// find process builder
+	ps, err := f.buildProcesses(p, c)
+	if err != nil {
+		log.Warnf("find process builder error for pid: %d, err: %v", p.Pid, err)
+		return detectedProcesses, false
 	}
-	return nil
+
+	for _, pro := range ps {
+		detectedProcesses = append(detectedProcesses, pro)
+	}
+	f.processCache.Add(processCahceKey, ps)
+	return detectedProcesses, true
 }
 
 func (f *ProcessFinder) buildProcesses(p *process.Process, pc *PodContainer) ([]*Process, error) {
@@ -299,13 +305,13 @@ func (f *ProcessFinder) DetectType() api.ProcessDetectType {
 	return api.Kubernetes
 }
 
-func (f *ProcessFinder) ValidateProcessIsSame(p1, p2 base.DetectedProcess) bool {
+func (f *ProcessFinder) ValidateProcessIsSame(p1, p2 api.DetectedProcess) bool {
 	k1 := p1.(*Process)
 	k2 := p2.(*Process)
 	return p1.Pid() == p2.Pid() && k1.cmd == k2.cmd && p1.Entity().SameWith(p2.Entity())
 }
 
-func (f *ProcessFinder) BuildNecessaryProperties(ps base.DetectedProcess) []*commonv3.KeyStringValuePair {
+func (f *ProcessFinder) BuildNecessaryProperties(ps api.DetectedProcess) []*commonv3.KeyStringValuePair {
 	return []*commonv3.KeyStringValuePair{
 		{
 			Key:   "support_ebpf_profiling",
@@ -314,7 +320,7 @@ func (f *ProcessFinder) BuildNecessaryProperties(ps base.DetectedProcess) []*com
 	}
 }
 
-func (f *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps base.DetectedProcess) *v3.EBPFProcessProperties {
+func (f *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps api.DetectedProcess) *v3.EBPFProcessProperties {
 	k8sProcess := &v3.EBPFKubernetesProcessMetadata{}
 	k8sProcess.Pid = ps.Pid()
 	k8sProcess.Entity = &v3.EBPFProcessEntityMetadata{
@@ -357,7 +363,7 @@ func (f *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps b
 	return properties
 }
 
-func (f *ProcessFinder) ParseProcessID(ps base.DetectedProcess, downstream *v3.EBPFProcessDownstream) string {
+func (f *ProcessFinder) ParseProcessID(ps api.DetectedProcess, downstream *v3.EBPFProcessDownstream) string {
 	if downstream.GetK8SProcess() == nil {
 		return ""
 	}
@@ -367,3 +373,17 @@ func (f *ProcessFinder) ParseProcessID(ps base.DetectedProcess, downstream *v3.E
 	}
 	return ""
 }
+
+func (f *ProcessFinder) ShouldMonitor(pid int32) bool {
+	newProcess, err := process.NewProcess(pid)
+	if err != nil {
+		return false
+	}
+	// analyze the process needs to be monitored
+	processes, monitor := f.buildProcess(newProcess, nil, f.registry.BuildPodContainers())
+	if !monitor || len(processes) == 0 {
+		return false
+	}
+	f.manager.AddDetectedProcess(processes)
+	return true
+}
diff --git a/pkg/process/finders/kubernetes/process.go b/pkg/process/finders/kubernetes/process.go
index 5bae8ed..9879258 100644
--- a/pkg/process/finders/kubernetes/process.go
+++ b/pkg/process/finders/kubernetes/process.go
@@ -95,3 +95,11 @@ func (p *Process) ExposePorts() []int {
 
 	return result
 }
+
+func (p *Process) ExposeHosts() []string {
+	result := make([]string, 0)
+	for _, ip := range p.podContainer.Pod.Status.PodIPs {
+		result = append(result, ip.IP)
+	}
+	return result
+}
diff --git a/pkg/process/finders/manager.go b/pkg/process/finders/manager.go
index 8c59368..03ecf69 100644
--- a/pkg/process/finders/manager.go
+++ b/pkg/process/finders/manager.go
@@ -48,6 +48,8 @@ type ProcessManager struct {
 type ProcessManagerWithFinder struct {
 	*ProcessManager
 	finderType api.ProcessDetectType
+
+	lastSync []api.DetectedProcess
 }
 
 func NewProcessManager(ctx context.Context, moduleManager *module.Manager,
@@ -117,10 +119,23 @@ func (p *ProcessManagerWithFinder) GetModuleManager() *module.Manager {
 	return p.moduleManager
 }
 
-func (p *ProcessManagerWithFinder) SyncAllProcessInFinder(processes []base.DetectedProcess) {
+func (p *ProcessManagerWithFinder) SyncAllProcessInFinder(processes []api.DetectedProcess) {
 	p.storage.SyncAllProcessInFinder(p.finderType, processes)
 }
 
+func (p *ProcessManagerWithFinder) AddDetectedProcess(processes []api.DetectedProcess) {
+	if len(p.lastSync) == 0 {
+		p.SyncAllProcessInFinder(processes)
+		p.lastSync = processes
+		return
+	}
+	// fetch existing process, add the new processes, finally, re-sync
+	detectedProcesses := make([]api.DetectedProcess, len(processes)+len(p.lastSync))
+	detectedProcesses = append(detectedProcesses, p.lastSync...)
+	detectedProcesses = append(detectedProcesses, processes...)
+	p.SyncAllProcessInFinder(detectedProcesses)
+}
+
 func (m *ProcessManager) GetAllProcesses() []api.ProcessInterface {
 	return m.storage.GetAllProcesses()
 }
@@ -144,3 +159,13 @@ func (m *ProcessManager) AddListener(listener api.ProcessListener) {
 func (m *ProcessManager) DeleteListener(listener api.ProcessListener) {
 	m.storage.DeleteListener(listener)
 }
+
+func (m *ProcessManager) ShouldMonitor(pid int32) bool {
+	monitor := false
+	for _, finder := range m.finders {
+		if finder.ShouldMonitor(pid) {
+			monitor = true
+		}
+	}
+	return monitor
+}
diff --git a/pkg/process/finders/scanner/finder.go b/pkg/process/finders/scanner/finder.go
index 81648d0..e932fbf 100644
--- a/pkg/process/finders/scanner/finder.go
+++ b/pkg/process/finders/scanner/finder.go
@@ -83,13 +83,29 @@ func (p *ProcessFinder) DetectType() api.ProcessDetectType {
 	return api.Scanner
 }
 
-func (p *ProcessFinder) ValidateProcessIsSame(p1, p2 base.DetectedProcess) bool {
+func (p *ProcessFinder) ShouldMonitor(pid int32) bool {
+	curProcess, err := process.NewProcess(pid)
+	if err != nil {
+		return false
+	}
+	var buildProcess *Process
+	if p.conf.ScanMode == Regex {
+		buildProcess = p.regexBuildProcess(curProcess)
+	}
+	if buildProcess != nil {
+		p.manager.AddDetectedProcess([]api.DetectedProcess{buildProcess})
+		return true
+	}
+	return false
+}
+
+func (p *ProcessFinder) ValidateProcessIsSame(p1, p2 api.DetectedProcess) bool {
 	vm1 := p1.(*Process)
 	vm2 := p2.(*Process)
 	return p1.Pid() == p2.Pid() && vm1.cmd == vm2.cmd && p1.Entity().SameWith(p2.Entity())
 }
 
-func (p *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps base.DetectedProcess) *v3.EBPFProcessProperties {
+func (p *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps api.DetectedProcess) *v3.EBPFProcessProperties {
 	hostProcess := &v3.EBPFHostProcessMetadata{}
 	hostProcess.Pid = ps.Pid()
 	hostProcess.Entity = &v3.EBPFProcessEntityMetadata{
@@ -120,7 +136,7 @@ func (p *ProcessFinder) BuildEBPFProcess(ctx *base.BuildEBPFProcessContext, ps b
 	return properties
 }
 
-func (p *ProcessFinder) BuildNecessaryProperties(ps base.DetectedProcess) []*commonv3.KeyStringValuePair {
+func (p *ProcessFinder) BuildNecessaryProperties(ps api.DetectedProcess) []*commonv3.KeyStringValuePair {
 	return []*commonv3.KeyStringValuePair{
 		{
 			Key:   "support_ebpf_profiling",
@@ -129,7 +145,7 @@ func (p *ProcessFinder) BuildNecessaryProperties(ps base.DetectedProcess) []*com
 	}
 }
 
-func (p *ProcessFinder) ParseProcessID(ps base.DetectedProcess, downstream *v3.EBPFProcessDownstream) string {
+func (p *ProcessFinder) ParseProcessID(ps api.DetectedProcess, downstream *v3.EBPFProcessDownstream) string {
 	if downstream.GetHostProcess() == nil {
 		return ""
 	}
@@ -156,7 +172,7 @@ func (p *ProcessFinder) startWatch() {
 }
 
 func (p *ProcessFinder) findAndReportProcesses() {
-	var detectFunc func() ([]base.DetectedProcess, error)
+	var detectFunc func() ([]api.DetectedProcess, error)
 	if p.conf.ScanMode == Regex {
 		detectFunc = p.regexFindProcesses
 	} else if p.conf.ScanMode == Agent {
@@ -170,7 +186,7 @@ func (p *ProcessFinder) findAndReportProcesses() {
 	}
 }
 
-func (p *ProcessFinder) regexFindProcesses() ([]base.DetectedProcess, error) {
+func (p *ProcessFinder) regexFindProcesses() ([]api.DetectedProcess, error) {
 	// find all process
 	processes, err := p.regexFindMatchedProcesses()
 	if err != nil {
@@ -178,7 +194,7 @@ func (p *ProcessFinder) regexFindProcesses() ([]base.DetectedProcess, error) {
 	}
 
 	// report to the manager
-	psList := make([]base.DetectedProcess, 0)
+	psList := make([]api.DetectedProcess, 0)
 	for _, ps := range processes {
 		psList = append(psList, ps)
 	}
@@ -208,14 +224,14 @@ func (p *ProcessFinder) getProcessTempDir(pro *process.Process) (string, error)
 	return "", fmt.Errorf("could not found tmp directory for pid: %d", pro.Pid)
 }
 
-func (p *ProcessFinder) agentFindProcesses() ([]base.DetectedProcess, error) {
+func (p *ProcessFinder) agentFindProcesses() ([]api.DetectedProcess, error) {
 	// all system processes
 	processes, err := process.ProcessesWithContext(p.ctx)
 	if err != nil {
 		return nil, err
 	}
 	// find all matches processes
-	findedProcesses := make([]base.DetectedProcess, 0)
+	findedProcesses := make([]api.DetectedProcess, 0)
 	for _, pro := range processes {
 		// already contains the processes
 		pid := pro.Pid
@@ -323,6 +339,30 @@ func (p *ProcessFinder) buildProcessFromAgentMetadata(pro *process.Process, meta
 	return NewProcessByAgent(pro, cmdline, agent)
 }
 
+func (p *ProcessFinder) regexBuildProcess(pro *process.Process) *Process {
+	finderConfig, cmdline, err := p.findMatchesFinder(pro)
+	if err != nil {
+		log.Warnf("failed to match process %d, reason: %v", pro.Pid, err)
+		return nil
+	}
+	if finderConfig == nil {
+		return nil
+	}
+
+	// build the linux process and add to the list
+	ps := NewProcessByRegex(pro, cmdline, finderConfig)
+	ps.entity.Layer = finderConfig.Layer
+	ps.entity.ServiceName, err = p.buildEntity(err, ps, finderConfig.serviceNameBuilder)
+	ps.entity.InstanceName, err = p.buildEntity(err, ps, finderConfig.instanceNameBuilder)
+	ps.entity.ProcessName, err = p.buildEntity(err, ps, finderConfig.processNameBuilder)
+	ps.entity.Labels = finderConfig.ParsedLabels
+	if err != nil {
+		log.Warnf("failed to build the process data for pid: %d, reason: %v", pro.Pid, err)
+		return nil
+	}
+	return ps
+}
+
 func (p *ProcessFinder) regexFindMatchedProcesses() ([]*Process, error) {
 	// all system processes
 	processes, err := process.ProcessesWithContext(p.ctx)
@@ -332,28 +372,8 @@ func (p *ProcessFinder) regexFindMatchedProcesses() ([]*Process, error) {
 	// find all matches processes
 	findedProcesses := make([]*Process, 0)
 	for _, pro := range processes {
-		// find the matched process finder
-		finderConfig, cmdline, err := p.findMatchesFinder(pro)
-		if err != nil {
-			log.Warnf("failed to match process %d, reason: %v", pro.Pid, err)
-			continue
-		}
-		if finderConfig == nil {
-			continue
-		}
-
-		// build the linux process and add to the list
-		ps := NewProcessByRegex(pro, cmdline, finderConfig)
-		ps.entity.Layer = finderConfig.Layer
-		ps.entity.ServiceName, err = p.buildEntity(err, ps, finderConfig.serviceNameBuilder)
-		ps.entity.InstanceName, err = p.buildEntity(err, ps, finderConfig.instanceNameBuilder)
-		ps.entity.ProcessName, err = p.buildEntity(err, ps, finderConfig.processNameBuilder)
-		ps.entity.Labels = finderConfig.ParsedLabels
-		if err != nil {
-			log.Warnf("failed to build the process data for pid: %d, reason: %v", pro.Pid, err)
-			continue
-		} else {
-			findedProcesses = append(findedProcesses, ps)
+		if curProcess := p.regexBuildProcess(pro); curProcess != nil {
+			findedProcesses = append(findedProcesses, curProcess)
 		}
 	}
 	if len(findedProcesses) == 0 {
diff --git a/pkg/process/finders/scanner/process.go b/pkg/process/finders/scanner/process.go
index ae5ebed..87eeb3c 100644
--- a/pkg/process/finders/scanner/process.go
+++ b/pkg/process/finders/scanner/process.go
@@ -28,6 +28,8 @@ import (
 	"github.com/apache/skywalking-rover/pkg/tools/profiling"
 )
 
+var listenStatus = "LISTEN"
+
 type Process struct {
 	// original reference
 	original     *process.Process
@@ -116,13 +118,27 @@ func (p *Process) ExposePorts() []int {
 	}
 	ports := make([]int, 0)
 	for _, con := range connections {
-		if con.Status == "LISTEN" {
+		if con.Status == listenStatus {
 			ports = append(ports, int(con.Laddr.Port))
 		}
 	}
 	return ports
 }
 
+func (p *Process) ExposeHosts() []string {
+	connections, err := p.original.Connections()
+	if err != nil {
+		log.Warnf("error getting the process connections, pid: %d, error: %v", p.pid, err)
+	}
+	hosts := make([]string, 0)
+	for _, con := range connections {
+		if con.Status == listenStatus {
+			hosts = append(hosts, con.Laddr.IP)
+		}
+	}
+	return hosts
+}
+
 func requiredNotNull(err error, key, value string) error {
 	if err != nil {
 		return err
diff --git a/pkg/process/finders/storage.go b/pkg/process/finders/storage.go
index f382f2f..16314ee 100644
--- a/pkg/process/finders/storage.go
+++ b/pkg/process/finders/storage.go
@@ -237,7 +237,7 @@ func (s *ProcessStorage) processesReport(waitReportProcesses []*ProcessContext)
 	return nil
 }
 
-func (s *ProcessStorage) SyncAllProcessInFinder(finder api.ProcessDetectType, processes []base.DetectedProcess) {
+func (s *ProcessStorage) SyncAllProcessInFinder(finder api.ProcessDetectType, processes []api.DetectedProcess) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
@@ -249,7 +249,11 @@ func (s *ProcessStorage) SyncAllProcessInFinder(finder api.ProcessDetectType, pr
 		existingProcessHasFounded[p] = false
 	}
 
+	addProcessBuilder := s.newProcessEventBuilder(ProcessOperateAdd)
 	for _, syncProcess := range processes {
+		if syncProcess == nil {
+			continue
+		}
 		founded := false
 		for _, existingProcess := range existingProcesses {
 			if syncProcess.Pid() == existingProcess.Pid() && syncProcess.Entity().SameWith(existingProcess.Entity()) {
@@ -262,10 +266,13 @@ func (s *ProcessStorage) SyncAllProcessInFinder(finder api.ProcessDetectType, pr
 
 		// if not found in existing processes, need to add this process
 		if !founded {
-			newProcesses = append(newProcesses, s.constructNewProcessContext(finder, syncProcess))
+			processContext := s.constructNewProcessContext(finder, syncProcess)
+			newProcesses = append(newProcesses, processContext)
+			addProcessBuilder.AddProcess(syncProcess.Pid(), newProcesses[len(newProcesses)-1])
 			log.Infof("detected new process: pid: %d, entity: %s", syncProcess.Pid(), syncProcess.Entity())
 		}
 	}
+	addProcessBuilder.Send()
 
 	// log the dead processes
 	eventBuilder := s.newProcessEventBuilder(ProcessOperateDelete)
@@ -281,7 +288,7 @@ func (s *ProcessStorage) SyncAllProcessInFinder(finder api.ProcessDetectType, pr
 	eventBuilder.Send()
 }
 
-func (s *ProcessStorage) constructNewProcessContext(finder api.ProcessDetectType, process base.DetectedProcess) *ProcessContext {
+func (s *ProcessStorage) constructNewProcessContext(finder api.ProcessDetectType, process api.DetectedProcess) *ProcessContext {
 	exporsedPorts := make(map[int]bool)
 	for _, p := range process.ExposePorts() {
 		exporsedPorts[p] = true
diff --git a/pkg/process/module.go b/pkg/process/module.go
index 769880e..3a8903f 100644
--- a/pkg/process/module.go
+++ b/pkg/process/module.go
@@ -98,3 +98,11 @@ func (m *Module) AddListener(listener api.ProcessListener) {
 func (m *Module) DeleteListener(listener api.ProcessListener) {
 	m.manager.DeleteListener(listener)
 }
+
+func (m *Module) ShouldMonitor(pid int32) bool {
+	return m.manager.ShouldMonitor(pid)
+}
+
+func (m *Module) NodeName() string {
+	return m.config.Kubernetes.NodeName
+}
diff --git a/pkg/profiling/continuous/checker/bpf/network/reader.go b/pkg/profiling/continuous/checker/bpf/network/reader.go
index cacaa98..721e17f 100644
--- a/pkg/profiling/continuous/checker/bpf/network/reader.go
+++ b/pkg/profiling/continuous/checker/bpf/network/reader.go
@@ -18,12 +18,12 @@
 package network
 
 import (
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 type BufferDirection uint8
 
-var protocolAnalyzers map[events.ConnectionProtocol]ProtocolAnalyzer
+var protocolAnalyzers map[enums.ConnectionProtocol]ProtocolAnalyzer
 
 var (
 	BufferDirectionRequest  BufferDirection = 1
@@ -31,14 +31,14 @@ var (
 )
 
 func init() {
-	protocolAnalyzers = make(map[events.ConnectionProtocol]ProtocolAnalyzer)
-	protocolAnalyzers[events.ConnectionProtocolHTTP] = NewHTTP1Analyzer()
+	protocolAnalyzers = make(map[enums.ConnectionProtocol]ProtocolAnalyzer)
+	protocolAnalyzers[enums.ConnectionProtocolHTTP] = NewHTTP1Analyzer()
 }
 
 type networkBufferInBPF struct {
 	Timestamp  uint64
 	ChannelRef uint64
-	Protocol   events.ConnectionProtocol
+	Protocol   enums.ConnectionProtocol
 	Direction  BufferDirection
 	Size       uint16
 	Pid        uint32
diff --git a/pkg/profiling/task/network/analyze/base/connection.go b/pkg/profiling/task/network/analyze/base/connection.go
index cad759b..2bd1cc9 100644
--- a/pkg/profiling/task/network/analyze/base/connection.go
+++ b/pkg/profiling/task/network/analyze/base/connection.go
@@ -19,7 +19,7 @@ package base
 
 import (
 	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 type ConnectionContext struct {
@@ -30,11 +30,11 @@ type ConnectionContext struct {
 	SocketFD         uint32
 	LocalProcesses   []api.ProcessInterface
 	ConnectionClosed bool
-	Protocol         events.ConnectionProtocol
+	Protocol         enums.ConnectionProtocol
 	IsSSL            bool
 
 	// socket metadata
-	Role       events.ConnectionRole
+	Role       enums.ConnectionRole
 	LocalIP    string
 	LocalPort  uint16
 	RemoteIP   string
@@ -67,7 +67,7 @@ type ActiveConnectionInBPF struct {
 	RandomID     uint64
 	Pid          uint32
 	SocketFD     uint32
-	Role         events.ConnectionRole
+	Role         enums.ConnectionRole
 	SocketFamily uint32
 
 	RemoteAddrV4   uint32
@@ -91,7 +91,7 @@ type ActiveConnectionInBPF struct {
 	_ uint64
 
 	// protocol of connection
-	Protocol events.ConnectionProtocol
+	Protocol enums.ConnectionProtocol
 	// the connect event is already sent
 	ConnectEventIsSent uint8
 	IsSSL              uint8
diff --git a/pkg/profiling/task/network/analyze/base/context.go b/pkg/profiling/task/network/analyze/base/context.go
index 3f09987..de60778 100644
--- a/pkg/profiling/task/network/analyze/base/context.go
+++ b/pkg/profiling/task/network/analyze/base/context.go
@@ -22,15 +22,15 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"net"
 	"sync"
-	"unsafe"
 
 	"github.com/apache/skywalking-rover/pkg/module"
 	"github.com/apache/skywalking-rover/pkg/process/api"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/bpf"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/ip"
 
 	"github.com/cilium/ebpf"
 
@@ -129,7 +129,7 @@ func (c *AnalyzerContext) handleSocketParseQueue(ctx context.Context) {
 	for {
 		select {
 		case cc := <-c.sockParseQueue:
-			socket, err := ParseSocket(cc.LocalPid, cc.SocketFD)
+			socket, err := ip.ParseSocket(cc.LocalPid, cc.SocketFD)
 			if err != nil {
 				// if the remote port of connection is empty, then this connection not available basically
 				if cc.RemotePort == 0 {
@@ -168,20 +168,20 @@ func (c *AnalyzerContext) handleSocketConnectEvent(data interface{}) {
 		con.RemotePort = uint16(event.RemoteAddrPort)
 		con.LocalPort = uint16(event.LocalAddrPort)
 		if event.SocketFamily == unix.AF_INET {
-			con.LocalIP = parseAddressV4(event.LocalAddrV4)
-			con.RemoteIP = parseAddressV4(event.RemoteAddrV4)
+			con.LocalIP = ip.ParseIPV4(event.LocalAddrV4)
+			con.RemoteIP = ip.ParseIPV4(event.RemoteAddrV4)
 		} else {
-			con.LocalIP = parseAddressV6(event.LocalAddrV6)
-			con.RemoteIP = parseAddressV6(event.RemoteAddrV6)
+			con.LocalIP = ip.ParseIPV6(event.LocalAddrV6)
+			con.RemoteIP = ip.ParseIPV6(event.RemoteAddrV6)
 		}
 	} else {
 		// if the remote address exists then setting it
 		if event.RemoteAddrPort != 0 {
 			con.RemotePort = uint16(event.RemoteAddrPort)
 			if event.SocketFamily == unix.AF_INET {
-				con.RemoteIP = parseAddressV4(event.RemoteAddrV4)
+				con.RemoteIP = ip.ParseIPV4(event.RemoteAddrV4)
 			} else {
-				con.RemoteIP = parseAddressV6(event.RemoteAddrV6)
+				con.RemoteIP = ip.ParseIPV6(event.RemoteAddrV6)
 			}
 		}
 		c.sockParseQueue <- con
@@ -192,7 +192,7 @@ func (c *AnalyzerContext) handleSocketConnectEvent(data interface{}) {
 		l.ReceiveNewConnection(con, event)
 	}
 
-	// add to the context
+	// add to the common
 	c.saveActiveConnection(con)
 }
 
@@ -303,10 +303,10 @@ func (c *AnalyzerContext) lookupTheActiveConnectionInBPf(connection *ConnectionC
 			log.Debugf("found the active connection, conid: %d, data: %s", connection.ConnectionID, string(marshal))
 		}
 
-		if connection.Role == events.ConnectionRoleUnknown && activeConnection.Role != events.ConnectionRoleUnknown {
+		if connection.Role == enums.ConnectionRoleUnknown && activeConnection.Role != enums.ConnectionRoleUnknown {
 			connection.Role = activeConnection.Role
 		}
-		if connection.Protocol == events.ConnectionProtocolUnknown && activeConnection.Protocol != events.ConnectionProtocolUnknown {
+		if connection.Protocol == enums.ConnectionProtocolUnknown && activeConnection.Protocol != enums.ConnectionProtocolUnknown {
 			connection.Protocol = activeConnection.Protocol
 		}
 		if !connection.IsSSL && activeConnection.IsSSL == 1 {
@@ -334,11 +334,11 @@ func (c *AnalyzerContext) processCachedCloseEvents() {
 			}
 			cc := c.NewConnectionContext(event.ConID, event.RandomID, event.Pid, event.SocketFD, processes, true)
 			if event.SocketFamily == unix.AF_INET {
-				cc.RemoteIP = parseAddressV4(event.RemoteAddrV4)
-				cc.LocalIP = parseAddressV4(event.LocalAddrV4)
+				cc.RemoteIP = ip.ParseIPV4(event.RemoteAddrV4)
+				cc.LocalIP = ip.ParseIPV4(event.LocalAddrV4)
 			} else if event.SocketFamily == unix.AF_INET6 {
-				cc.RemoteIP = parseAddressV6(event.RemoteAddrV6)
-				cc.LocalIP = parseAddressV6(event.LocalAddrV6)
+				cc.RemoteIP = ip.ParseIPV6(event.RemoteAddrV6)
+				cc.LocalIP = ip.ParseIPV6(event.LocalAddrV6)
 			} else {
 				continue
 			}
@@ -376,10 +376,10 @@ func (c *AnalyzerContext) foundAndDeleteConnection(event *events.SocketCloseEven
 func (c *AnalyzerContext) combineClosedConnection(active *ConnectionContext, closed *events.SocketCloseEvent) *ConnectionContext {
 	active.ConnectionClosed = true
 
-	if active.Role == events.ConnectionRoleUnknown && closed.Role != events.ConnectionRoleUnknown {
+	if active.Role == enums.ConnectionRoleUnknown && closed.Role != enums.ConnectionRoleUnknown {
 		active.Role = closed.Role
 	}
-	if active.Protocol == events.ConnectionProtocolUnknown && closed.Protocol != events.ConnectionProtocolUnknown {
+	if active.Protocol == enums.ConnectionProtocolUnknown && closed.Protocol != enums.ConnectionProtocolUnknown {
 		active.Protocol = closed.Protocol
 	}
 	if !active.IsSSL && closed.IsSSL == 1 {
@@ -412,11 +412,3 @@ func (c *AnalyzerContext) appendClosedConnection(con *ConnectionContext) {
 
 	c.closedConnections = append(c.closedConnections, con)
 }
-
-func parseAddressV4(val uint32) string {
-	return net.IP((*(*[net.IPv4len]byte)(unsafe.Pointer(&val)))[:]).String()
-}
-
-func parseAddressV6(val [16]uint8) string {
-	return net.IP((*(*[net.IPv6len]byte)(unsafe.Pointer(&val)))[:]).String()
-}
diff --git a/pkg/profiling/task/network/analyze/base/metrics.go b/pkg/profiling/task/network/analyze/base/metrics.go
index 3514d02..60ec728 100644
--- a/pkg/profiling/task/network/analyze/base/metrics.go
+++ b/pkg/profiling/task/network/analyze/base/metrics.go
@@ -22,8 +22,8 @@ import (
 	"time"
 
 	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	"github.com/apache/skywalking-rover/pkg/tools"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
 	logv3 "skywalking.apache.org/repo/goapi/collect/logging/v3"
@@ -96,11 +96,11 @@ func (m *MetricsBuilder) MetricPrefix() string {
 	return m.prefix
 }
 
-func (m *MetricsBuilder) BuildBasicMeterLabels(traffic *ProcessTraffic, local api.ProcessInterface) (events.ConnectionRole, []*agentv3.Label) {
+func (m *MetricsBuilder) BuildBasicMeterLabels(traffic *ProcessTraffic, local api.ProcessInterface) (enums.ConnectionRole, []*agentv3.Label) {
 	curRole := traffic.Role
 	// add the default role
-	if curRole == events.ConnectionRoleUnknown {
-		curRole = events.ConnectionRoleClient
+	if curRole == enums.ConnectionRoleUnknown {
+		curRole = enums.ConnectionRoleClient
 	}
 	labels := make([]*agentv3.Label, 0)
 
diff --git a/pkg/profiling/task/network/analyze/base/tcpresolver.go b/pkg/profiling/task/network/analyze/base/tcpresolver.go
deleted file mode 100644
index 2af0e6e..0000000
--- a/pkg/profiling/task/network/analyze/base/tcpresolver.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Licensed to Apache Software Foundation (ASF) under one or more contributor
-// license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright
-// ownership. Apache Software Foundation (ASF) licenses this file to you under
-// the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-package base
-
-import (
-	"encoding/binary"
-	"fmt"
-	"net"
-	"os"
-	"regexp"
-	"strconv"
-	"strings"
-
-	"github.com/hashicorp/go-multierror"
-
-	"github.com/apache/skywalking-rover/pkg/tools/host"
-)
-
-var (
-	notBlankRegex = regexp.MustCompile(`\s+`)
-	ipv4StrLen    = 8
-	ipv6StrLen    = 32
-)
-
-type SocketPair struct {
-	SrcIP    string
-	SrcPort  uint16
-	DestIP   string
-	DestPort uint16
-}
-
-func ParseSocket(pid, sockfd uint32) (*SocketPair, error) {
-	link := fmt.Sprintf("/proc/%d/fd/%d", pid, sockfd)
-	dest, err := os.Readlink(host.GetFileInHost(link))
-	if err != nil {
-		return nil, fmt.Errorf("could not read the socket real link: %v", err)
-	}
-	if !strings.HasPrefix(dest, "socket:[") {
-		return nil, fmt.Errorf("current file is not socket: %s", dest)
-	}
-
-	inode := strings.TrimSuffix(strings.TrimPrefix(dest, "socket:["), "]")
-	var s *SocketPair
-	s, err = foundAddressByFile(s, err, fmt.Sprintf(host.GetFileInHost("/proc/%d/net/tcp"), pid), inode)
-	s, err = foundAddressByFile(s, err, fmt.Sprintf(host.GetFileInHost("/proc/%d/net/tcp6"), pid), inode)
-	return s, err
-}
-
-func foundAddressByFile(s *SocketPair, exitedError error, filename, inode string) (*SocketPair, error) {
-	if s != nil {
-		return s, nil
-	}
-	data, err := os.ReadFile(filename)
-	if err != nil {
-		return nil, multierror.Append(exitedError, err)
-	}
-
-	lines := strings.Split(string(data), "\n")
-	for _, line := range lines[1 : len(lines)-1] {
-		source := notBlankRegex.Split(strings.TrimSpace(line), -1)
-		if len(source) < 10 {
-			continue
-		}
-		tcpINode := source[9]
-		if tcpINode != inode {
-			continue
-		}
-
-		// ignore local listenning records
-		destIP, destPort, err := parseAddr(source[2])
-		if err != nil {
-			return nil, multierror.Append(exitedError, fmt.Errorf("parsing address in file failure: %s, error: %s", filename, err))
-		}
-
-		// source ip and port
-		ip, port, err := parseAddr(source[1])
-		if err != nil {
-			return nil, multierror.Append(exitedError, fmt.Errorf("parsing address in file failure: %s, error: %s", filename, err))
-		}
-
-		return &SocketPair{
-			SrcIP:    ip,
-			SrcPort:  port,
-			DestIP:   destIP,
-			DestPort: destPort,
-		}, nil
-	}
-	return nil, multierror.Append(exitedError, fmt.Errorf("could not found the socket: %s, in file: %s", inode, filename))
-}
-
-func parseAddr(str string) (ipAddr string, port uint16, err error) {
-	fields := strings.Split(str, ":")
-	if len(fields) < 2 {
-		return "", 0, fmt.Errorf("netstat: not enough fields: %v", fields)
-	}
-	var ip net.IP
-	switch len(fields[0]) {
-	case ipv4StrLen:
-		ip, err = parseIPv4(fields[0])
-	case ipv6StrLen:
-		ip, err = parseIPv6(fields[0])
-	default:
-		err = fmt.Errorf("netstat: bad formatted string: %v", fields[0])
-	}
-	if err != nil {
-		return "", 0, err
-	}
-	v, err := strconv.ParseUint(fields[1], 16, 16)
-	if err != nil {
-		return "", 0, err
-	}
-	return ip.String(), uint16(v), nil
-}
-
-func parseIPv4(s string) (net.IP, error) {
-	v, err := strconv.ParseUint(s, 16, 32)
-	if err != nil {
-		return nil, err
-	}
-	ip := make(net.IP, net.IPv4len)
-	binary.LittleEndian.PutUint32(ip, uint32(v))
-	return ip, nil
-}
-
-func parseIPv6(s string) (net.IP, error) {
-	ip := make(net.IP, net.IPv6len)
-	const grpLen = 4
-	i, j := 0, 4
-	for s != "" {
-		grp := s[0:8]
-		u, err := strconv.ParseUint(grp, 16, 32)
-		binary.LittleEndian.PutUint32(ip[i:j], uint32(u))
-		if err != nil {
-			return nil, err
-		}
-		i, j = i+grpLen, j+grpLen
-		s = s[8:]
-	}
-	return ip, nil
-}
diff --git a/pkg/profiling/task/network/analyze/base/traffic.go b/pkg/profiling/task/network/analyze/base/traffic.go
index 8e96e39..45495ed 100644
--- a/pkg/profiling/task/network/analyze/base/traffic.go
+++ b/pkg/profiling/task/network/analyze/base/traffic.go
@@ -22,8 +22,8 @@ import (
 
 	"github.com/apache/skywalking-rover/pkg/logger"
 	"github.com/apache/skywalking-rover/pkg/process/api"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	"github.com/apache/skywalking-rover/pkg/tools"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 var log = logger.GetLogger("profiling", "task", "network", "analyze")
@@ -50,8 +50,8 @@ type ProcessTraffic struct {
 	RemoteProcesses []api.ProcessInterface
 
 	// connection basic information
-	Role     events.ConnectionRole
-	Protocol events.ConnectionProtocol
+	Role     enums.ConnectionRole
+	Protocol enums.ConnectionProtocol
 	IsSSL    bool
 
 	// metrics
@@ -136,12 +136,12 @@ func (t *TrafficAnalyzer) CombineConnectionToTraffics(connections []*ConnectionC
 		pidToRemoteKey.LocalPid = con.LocalPid
 		pidToRemoteKey.RemoteIP = con.RemoteIP
 		// if connection role is not server side, then add the remote port
-		if con.Role != events.ConnectionRoleServer {
+		if con.Role != enums.ConnectionRoleServer {
 			// uniformly identified as a client
-			pidToRemoteKey.Role = events.ConnectionRoleClient
+			pidToRemoteKey.Role = enums.ConnectionRoleClient
 			pidToRemoteKey.RemotePort = con.RemotePort
 		} else {
-			pidToRemoteKey.Role = events.ConnectionRoleServer
+			pidToRemoteKey.Role = enums.ConnectionRoleServer
 		}
 		traffic := pidToRemoteTraffic[pidToRemoteKey]
 		traffic = t.generateOrCombineTraffic(traffic, con, 0)
@@ -187,20 +187,20 @@ func (t *ProcessTraffic) RemoteProcessIsProfiling() bool {
 }
 
 func (t *TrafficAnalyzer) tryingToGenerateTheRoleWhenRemotePidCannotFound(con *ConnectionContext) {
-	if con.Role != events.ConnectionRoleUnknown {
+	if con.Role != enums.ConnectionRoleUnknown {
 		return
 	}
 	// local process address or process could not found, then could analyze the role
 	if con.LocalPort == 0 || len(con.LocalProcesses) == 0 {
 		return
 	}
-	var role events.ConnectionRole
+	var role enums.ConnectionRole
 	// if port is expose, and remote address is not local pid
 	// then the role of connection is server side usually
 	if con.LocalProcesses[0].PortIsExpose(int(con.LocalPort)) {
-		role = events.ConnectionRoleServer
+		role = enums.ConnectionRoleServer
 	} else {
-		role = events.ConnectionRoleClient
+		role = enums.ConnectionRoleClient
 	}
 
 	con.Role = role
@@ -224,10 +224,10 @@ func (t *TrafficAnalyzer) generateOrCombineTraffic(traffic *ProcessTraffic, con
 	if len(traffic.LocalProcesses) == 0 && len(con.LocalProcesses) > 0 {
 		traffic.LocalProcesses = con.LocalProcesses
 	}
-	if traffic.Role == events.ConnectionRoleUnknown && con.Role != events.ConnectionRoleUnknown {
+	if traffic.Role == enums.ConnectionRoleUnknown && con.Role != enums.ConnectionRoleUnknown {
 		traffic.Role = con.Role
 	}
-	if traffic.Protocol == events.ConnectionProtocolUnknown && con.Protocol != events.ConnectionProtocolUnknown {
+	if traffic.Protocol == enums.ConnectionProtocolUnknown && con.Protocol != enums.ConnectionProtocolUnknown {
 		traffic.Protocol = con.Protocol
 	}
 	if !traffic.IsSSL && con.IsSSL {
@@ -284,7 +284,7 @@ func (t *TrafficAnalyzer) buildCache(connections []*ConnectionContext) {
 			}
 		} else if t.ipNotEmpty(con.RemoteIP, con.RemotePort) {
 			// if server side is envoy
-			if con.Role == events.ConnectionRoleServer && len(con.LocalProcesses) > 0 {
+			if con.Role == enums.ConnectionRoleServer && len(con.LocalProcesses) > 0 {
 				name, err := con.LocalProcesses[0].ExeName()
 				if err != nil {
 					log.Warnf("get process exe name failure, pid: %d, error: %v", con.LocalPid, err)
@@ -312,7 +312,7 @@ func (t *TrafficAnalyzer) buildCache(connections []*ConnectionContext) {
 func (t *TrafficAnalyzer) processExportPortAnalyze(con *ConnectionContext) {
 	// if the process exists, role of connection is server mode and local port is exists1
 	// add the detected port into the processes
-	if len(con.LocalProcesses) > 0 && con.Role == events.ConnectionRoleServer && con.LocalPort > 0 {
+	if len(con.LocalProcesses) > 0 && con.Role == enums.ConnectionRoleServer && con.LocalPort > 0 {
 		for _, p := range con.LocalProcesses {
 			p.DetectNewExposePort(int(con.LocalPort))
 		}
@@ -350,7 +350,7 @@ func (t *TrafficAnalyzer) findRemotePidWhenContainsFullAddress(con *ConnectionCo
 			log.Debugf("found in peer cache: %s:%d->%s:%d, pid: %d", con.RemoteIP, con.RemotePort, con.LocalIP, con.LocalPort, data.Pid)
 			// if current connection is unknown, but peer network has role, then just use the revert role
 			// such as: cur:(a->b) unknown, remote:(b->a) client, then current connection must have the server role
-			if con.Role == events.ConnectionRoleUnknown && data.Role != events.ConnectionRoleUnknown {
+			if con.Role == enums.ConnectionRoleUnknown && data.Role != enums.ConnectionRoleUnknown {
 				con.Role = data.Role.Revert()
 			}
 			return data.Pid
@@ -358,7 +358,7 @@ func (t *TrafficAnalyzer) findRemotePidWhenContainsFullAddress(con *ConnectionCo
 		log.Debugf("not found in peer cache: %s:%d->%s:%d", con.RemoteIP, con.RemotePort, con.LocalIP, con.LocalPort)
 
 		// if current role is client side, and localIP:port match to envoy
-		if con.Role == events.ConnectionRoleClient {
+		if con.Role == enums.ConnectionRoleClient {
 			// need update the remote address to real address
 			addr := t.envoyAcceptClientAddressCache[PeerAddress{
 				RemoteIP:   con.LocalIP,
@@ -473,19 +473,19 @@ type AddressWithPid struct {
 type PidMatchTrafficKey struct {
 	LocalPid  uint32
 	RemotePid uint32
-	Role      events.ConnectionRole
+	Role      enums.ConnectionRole
 }
 
 type PidToRemoteTrafficKey struct {
 	LocalPid   uint32
-	Role       events.ConnectionRole
+	Role       enums.ConnectionRole
 	RemoteIP   string
 	RemotePort uint16
 }
 
 type PidWithRole struct {
 	Pid  uint32
-	Role events.ConnectionRole
+	Role enums.ConnectionRole
 }
 
 func (t *TrafficAnalyzer) ipNotEmpty(ip string, port uint16) bool {
diff --git a/pkg/profiling/task/network/analyze/events/data.go b/pkg/profiling/task/network/analyze/events/data.go
index 46b0ae2..9ca242d 100644
--- a/pkg/profiling/task/network/analyze/events/data.go
+++ b/pkg/profiling/task/network/analyze/events/data.go
@@ -19,42 +19,14 @@ package events
 
 import (
 	"fmt"
-)
 
-type SocketDataBuffer interface {
-	// GenerateConnectionID for identity the buffer belong which connection
-	GenerateConnectionID() string
-	// BufferData of the buffer
-	BufferData() []byte
-	// TotalSize of socket data, the data may exceed the size of the BufferData()
-	TotalSize() uint64
-	// Direction of the data, send or receive
-	Direction() SocketDataDirection
-	// BufferStartPosition the buffer start index
-	BufferStartPosition() int
-	// BufferLen the buffer data length
-	BufferLen() int
-	// DataID data id of the buffer
-	DataID() uint64
-	// DataSequence the data sequence under same data id
-	DataSequence() int
-	// IsStart this buffer is start of the same data id
-	IsStart() bool
-	// IsFinished this buffer is finish of the same data id
-	IsFinished() bool
-	// HaveReduceDataAfterChunk check have reduced data after current buffer
-	HaveReduceDataAfterChunk() bool
-
-	// StartTime the data start timestamp
-	StartTime() uint64
-	// EndTime the data end timestamp
-	EndTime() uint64
-}
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
+)
 
 type SocketDataUploadEvent struct {
-	Protocol     ConnectionProtocol
+	Protocol     enums.ConnectionProtocol
 	HaveReduce   uint8
-	Direction0   SocketDataDirection
+	Direction0   enums.SocketDataDirection
 	Finished     uint8
 	Sequence0    uint16
 	DataLen      uint16
@@ -87,7 +59,7 @@ func (s *SocketDataUploadEvent) EndTime() uint64 {
 	return s.EndTime0
 }
 
-func (s *SocketDataUploadEvent) Direction() SocketDataDirection {
+func (s *SocketDataUploadEvent) Direction() enums.SocketDataDirection {
 	return s.Direction0
 }
 
@@ -119,37 +91,23 @@ func (s *SocketDataUploadEvent) HaveReduceDataAfterChunk() bool {
 	return s.HaveReduce == 1
 }
 
-type SocketDataEventLimited struct {
-	SocketDataBuffer
-	From int
-	Size int
-}
-
-func (s *SocketDataEventLimited) BufferData() []byte {
-	return s.SocketDataBuffer.BufferData()[s.From:s.Size]
-}
-
-func (s *SocketDataEventLimited) BufferLen() int {
-	return s.Size - s.From
-}
-
-func (s *SocketDataEventLimited) BufferStartPosition() int {
-	return s.From
-}
-
 type SocketDetailEvent struct {
 	ConnectionID     uint64
 	RandomID         uint64
-	DataID           uint64
+	DataID0          uint64
 	TotalPackageSize uint64
 	IfIndex          uint32
 	PackageCount     uint8
-	FuncName         SocketFunctionName
+	FuncName         enums.SocketFunctionName
 	RTTCount         uint8
-	Protocol         ConnectionProtocol
+	Protocol         enums.ConnectionProtocol
 	RTTTime          uint32
 }
 
+func (s *SocketDetailEvent) DataID() uint64 {
+	return s.DataID0
+}
+
 func (s *SocketDetailEvent) GenerateConnectionID() string {
 	return fmt.Sprintf("%d_%d", s.ConnectionID, s.RandomID)
 }
diff --git a/pkg/profiling/task/network/analyze/events/sockets.go b/pkg/profiling/task/network/analyze/events/sockets.go
index dca74f3..60e9842 100644
--- a/pkg/profiling/task/network/analyze/events/sockets.go
+++ b/pkg/profiling/task/network/analyze/events/sockets.go
@@ -17,6 +17,8 @@
 
 package events
 
+import "github.com/apache/skywalking-rover/pkg/tools/enums"
+
 // SocketConnectEvent Socket have been connection/accept event
 type SocketConnectEvent struct {
 	ConID        uint64
@@ -28,7 +30,7 @@ type SocketConnectEvent struct {
 	FuncName     uint32
 
 	// socket information if exists
-	Role           ConnectionRole
+	Role           enums.ConnectionRole
 	SocketFamily   uint32
 	RemoteAddrV4   uint32
 	RemoteAddrV6   [16]uint8
@@ -44,10 +46,10 @@ type SocketCloseEvent struct {
 	ExeTime  uint64
 	Pid      uint32
 	SocketFD uint32
-	Protocol ConnectionProtocol
+	Protocol enums.ConnectionProtocol
 	IsSSL    uint8
 	Fix      uint16
-	Role     ConnectionRole
+	Role     enums.ConnectionRole
 
 	SocketFamily   uint32
 	RemoteAddrV4   uint32
diff --git a/pkg/profiling/task/network/analyze/layer4/events.go b/pkg/profiling/task/network/analyze/layer4/events.go
index ecbc0fa..6cece95 100644
--- a/pkg/profiling/task/network/analyze/layer4/events.go
+++ b/pkg/profiling/task/network/analyze/layer4/events.go
@@ -21,7 +21,7 @@ import (
 	"encoding/json"
 
 	"github.com/apache/skywalking-rover/pkg/logger"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	"github.com/sirupsen/logrus"
 )
@@ -38,7 +38,7 @@ type SocketExceptionOperationEvent struct {
 	LocalAddrV4    uint32
 	LocalAddrV6    [16]uint8
 	LocalAddrPort  uint32
-	Type           events.SocketExceptionOperationType
+	Type           enums.SocketExceptionOperationType
 }
 
 func (l *Listener) handleSocketExceptionOperationEvent(data interface{}) {
@@ -60,9 +60,9 @@ func (l *Listener) handleSocketExceptionOperationEvent(data interface{}) {
 	}
 
 	switch event.Type {
-	case events.SocketExceptionOperationRetransmit:
+	case enums.SocketExceptionOperationRetransmit:
 		exceptionValue.RetransmitCount++
-	case events.SocketExceptionOperationDrop:
+	case enums.SocketExceptionOperationDrop:
 		exceptionValue.DropCount++
 	default:
 		log.Warnf("unknown socket exception operation type: %d", event.Type)
diff --git a/pkg/profiling/task/network/analyze/layer4/listener.go b/pkg/profiling/task/network/analyze/layer4/listener.go
index 31ba86d..0c16145 100644
--- a/pkg/profiling/task/network/analyze/layer4/listener.go
+++ b/pkg/profiling/task/network/analyze/layer4/listener.go
@@ -32,6 +32,7 @@ import (
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/bpf"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	v3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
 
@@ -129,13 +130,13 @@ func (l *Listener) PreFlushConnectionMetrics(ccs []*base.ConnectionWithBPF, bpfL
 
 		// add the histogram data
 		var histogram *SocketDataHistogramWithHistory
-		if key.DataDirection == events.SocketDataDirectionEgress {
-			if key.DataType == events.SocketDataStaticsTypeExeTime {
+		if key.DataDirection == enums.SocketDataDirectionEgress {
+			if key.DataType == enums.SocketDataStaticsTypeExeTime {
 				histogram = layer4.WriteExeTimeHistogram
-			} else if key.DataType == events.SocketDataStaticsTypeRTT {
+			} else if key.DataType == enums.SocketDataStaticsTypeRTT {
 				histogram = layer4.WriteRTTHistogram
 			}
-		} else if key.DataDirection == events.SocketDataDirectionIngress {
+		} else if key.DataDirection == enums.SocketDataDirectionIngress {
 			histogram = layer4.ReadExeTimeHistogram
 		}
 		if histogram == nil {
@@ -152,7 +153,7 @@ func (l *Listener) PreFlushConnectionMetrics(ccs []*base.ConnectionWithBPF, bpfL
 		}
 	}
 
-	// all the exception operations to the context
+	// all the exception operations to the common
 	exceptionContexts := l.cleanAndGetAllExceptionContexts()
 	l.combineExceptionToConnections(keyWithContext, exceptionContexts)
 	return nil
@@ -355,8 +356,8 @@ type HistogramDataKey struct {
 	ConnectionID  uint64
 	RandomID      uint64
 	Bucket        uint64
-	DataDirection events.SocketDataDirection
-	DataType      events.SocketDataStaticsType
+	DataDirection enums.SocketDataDirection
+	DataType      enums.SocketDataStaticsType
 	Fix           [6]byte
 }
 
diff --git a/pkg/profiling/task/network/analyze/layer7/listener.go b/pkg/profiling/task/network/analyze/layer7/listener.go
index 5c4c0ba..55dd187 100644
--- a/pkg/profiling/task/network/analyze/layer7/listener.go
+++ b/pkg/profiling/task/network/analyze/layer7/listener.go
@@ -33,6 +33,7 @@ import (
 	protocol "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/bpf"
 	"github.com/apache/skywalking-rover/pkg/tools/btf"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	"github.com/zekroTJA/timedmap"
 )
@@ -135,7 +136,7 @@ func (l *Listener) QueryConnection(conID, randomID uint64) *base.ConnectionConte
 	return nil
 }
 
-func (l *Listener) QueryProtocolMetrics(conMetrics *base.ConnectionMetricsContext, p events.ConnectionProtocol) protocol.Metrics {
+func (l *Listener) QueryProtocolMetrics(conMetrics *base.ConnectionMetricsContext, p enums.ConnectionProtocol) protocol.Metrics {
 	metrics := conMetrics.GetMetrics(ListenerName).(*protocols.ProtocolMetrics)
 	return metrics.GetProtocolMetrics(p)
 }
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/base/analyzer.go b/pkg/profiling/task/network/analyze/layer7/protocols/base/analyzer.go
index 3154a34..ac12d93 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/base/analyzer.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/base/analyzer.go
@@ -27,9 +27,9 @@ import (
 
 	"github.com/apache/skywalking-rover/pkg/logger"
 	profiling "github.com/apache/skywalking-rover/pkg/profiling/task/base"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 const (
@@ -96,7 +96,7 @@ func (a *ProtocolAnalyzer) ReceiveSocketDetail(ctx Context, event *events.Socket
 	connectionID := event.GenerateConnectionID()
 	connection := a.getConnection(ctx, event.ConnectionID, event.RandomID)
 
-	log.Debugf("receive detail from connection: %s, dataid: %d", connectionID, event.DataID)
+	log.Debugf("receive detail from connection: %s, dataid: %d", connectionID, event.DataID())
 	connection.buffer.AppendDetailEvent(event)
 }
 
@@ -221,7 +221,7 @@ func (a *ProtocolAnalyzer) generateConnectionInfoKey(connectionID, randomID uint
 
 type connectionInfo struct {
 	connectionID, randomID uint64
-	connectionProtocol     events.ConnectionProtocol
+	connectionProtocol     enums.ConnectionProtocol
 	buffer                 *buffer.Buffer
 	metrics                Metrics
 	metricsFromConnection  bool
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/base/protocol.go b/pkg/profiling/task/network/analyze/layer7/protocols/base/protocol.go
index 2a236b9..3ca7dcb 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/base/protocol.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/base/protocol.go
@@ -22,13 +22,12 @@ import (
 
 	profiling "github.com/apache/skywalking-rover/pkg/profiling/task/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 type Protocol interface {
-	Protocol() events.ConnectionProtocol
+	Protocol() enums.ConnectionProtocol
 	GenerateMetrics() Metrics
 	Init(config *profiling.TaskConfig)
 
@@ -39,7 +38,7 @@ type Protocol interface {
 
 type Context interface {
 	QueryConnection(connectionID, randomID uint64) *base.ConnectionContext
-	QueryProtocolMetrics(conMetrics *base.ConnectionMetricsContext, protocol events.ConnectionProtocol) Metrics
+	QueryProtocolMetrics(conMetrics *base.ConnectionMetricsContext, protocol enums.ConnectionProtocol) Metrics
 }
 
 type Metrics interface {
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/analyzer.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/analyzer.go
index e9bbd19..245e6dd 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/analyzer.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/analyzer.go
@@ -26,11 +26,10 @@ import (
 	"github.com/apache/skywalking-rover/pkg/logger"
 	profiling "github.com/apache/skywalking-rover/pkg/profiling/task/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	protocol "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	"github.com/sirupsen/logrus"
 )
@@ -72,8 +71,8 @@ func NewHTTP1Analyzer() protocol.Protocol {
 	}
 }
 
-func (h *Analyzer) Protocol() events.ConnectionProtocol {
-	return events.ConnectionProtocolHTTP
+func (h *Analyzer) Protocol() enums.ConnectionProtocol {
+	return enums.ConnectionProtocolHTTP
 }
 
 func (h *Analyzer) GenerateMetrics() protocol.Metrics {
@@ -151,11 +150,11 @@ func (h *Analyzer) handleResponse(connectionID uint64, metrics *ConnectionMetric
 
 	// append metrics
 	data := metrics.clientMetrics
-	side := events.ConnectionRoleClient
-	if request.Direction() == events.SocketDataDirectionIngress {
+	side := enums.ConnectionRoleClient
+	if request.Direction() == enums.SocketDataDirectionIngress {
 		// if receive the request, that's mean is server side
 		data = metrics.serverMetrics
-		side = events.ConnectionRoleServer
+		side = enums.ConnectionRoleServer
 	}
 	data.Append(h.sampleConfig, request, response)
 
@@ -226,7 +225,7 @@ func (m *ConnectionMetrics) FlushMetrics(traffic *base.ProcessTraffic, metricsBu
 		// if the remote process is profiling, then used the client side
 		localMetrics := m.clientMetrics
 		remoteMetrics := m.serverMetrics
-		if traffic.Role == events.ConnectionRoleServer {
+		if traffic.Role == enums.ConnectionRoleServer {
 			localMetrics = m.serverMetrics
 			remoteMetrics = m.clientMetrics
 		}
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/metrics.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/metrics.go
index f0db67f..28dd6d4 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/metrics.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/metrics.go
@@ -26,13 +26,14 @@ import (
 	"github.com/apache/skywalking-rover/pkg/process/api"
 	profiling "github.com/apache/skywalking-rover/pkg/profiling/task/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
-	protocol "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/metrics"
 	"github.com/apache/skywalking-rover/pkg/tools"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 	"github.com/apache/skywalking-rover/pkg/tools/host"
+	protocol "github.com/apache/skywalking-rover/pkg/tools/tracing"
 
 	"github.com/docker/go-units"
 
@@ -174,7 +175,7 @@ func (u *URIMetrics) String() string {
 }
 
 type Trace struct {
-	Trace      protocol.TracingContext
+	Trace      protocol.Context
 	RequestURI string
 	Request    *reader.Request
 	Response   *reader.Response
@@ -192,7 +193,7 @@ func (h *Trace) Flush(duration int64, process api.ProcessInterface, traffic *bas
 	logData.Tags = &logv3.LogTags{Data: make([]*commonv3.KeyStringValuePair, 0)}
 	logData.Tags.Data = append(logData.Tags.Data, &commonv3.KeyStringValuePair{Key: "LOG_KIND", Value: "NET_PROFILING_SAMPLED_TRACE"})
 
-	// trace context
+	// trace common
 	traceContext := &logv3.TraceContext{}
 	traceContext.TraceId = h.Trace.TraceID()
 	logData.TraceContext = traceContext
@@ -209,7 +210,7 @@ func (h *Trace) Flush(duration int64, process api.ProcessInterface, traffic *bas
 		Reason:        h.Type,
 		Status:        h.Response.Original().StatusCode,
 	}
-	if traffic.Role == events.ConnectionRoleClient {
+	if traffic.Role == enums.ConnectionRoleClient {
 		body.ClientProcess = &SamplingTraceLogProcess{ProcessID: process.ID()}
 		body.ServerProcess = NewHTTP1SampledTraceLogRemoteProcess(traffic, process)
 	} else {
@@ -278,7 +279,7 @@ func (h *Trace) appendHTTPEvent(attaches []*v3.SpanAttachedEvent, process api.Pr
 		TraceId:        h.Trace.TraceID(),
 		TraceSegmentId: h.Trace.TraceSegmentID(),
 		SpanId:         h.Trace.SpanID(),
-		Type:           h.Trace.Provider().Type,
+		Type:           h.Trace.Provider().SpanAttachType,
 	}
 	return append(attaches, event)
 }
@@ -290,12 +291,12 @@ func (h *Trace) appendSyscallEvents(attachEvents []*v3.SpanAttachedEvent, proces
 	dataIDCache := make(map[uint64]bool)
 	for e := headerDetails.Front(); e != nil; e = e.Next() {
 		event := e.Value.(*events.SocketDetailEvent)
-		dataIDCache[event.DataID] = true
+		dataIDCache[event.DataID()] = true
 		attachEvents = h.appendPerDetailEvent(attachEvents, process, traffic, event, message.HeaderBuffer())
 	}
 	for e := bodyDetails.Front(); e != nil; e = e.Next() {
 		event := e.Value.(*events.SocketDetailEvent)
-		if dataIDCache[event.DataID] {
+		if dataIDCache[event.DataID()] {
 			continue
 		}
 		attachEvents = h.appendPerDetailEvent(attachEvents, process, traffic, event, message.BodyBuffer())
@@ -306,7 +307,7 @@ func (h *Trace) appendSyscallEvents(attachEvents []*v3.SpanAttachedEvent, proces
 func (h *Trace) appendPerDetailEvent(attaches []*v3.SpanAttachedEvent, process api.ProcessInterface, _ *base.ProcessTraffic,
 	detail *events.SocketDetailEvent, buf *buffer.Buffer) []*v3.SpanAttachedEvent {
 	event := &v3.SpanAttachedEvent{}
-	dataBuffer := buf.FindFirstDataBuffer(detail.DataID)
+	dataBuffer := buf.FindFirstDataBuffer(detail.DataID())
 	if dataBuffer == nil {
 		return attaches
 	}
@@ -336,7 +337,7 @@ func (h *Trace) appendPerDetailEvent(attaches []*v3.SpanAttachedEvent, process a
 		TraceId:        h.Trace.TraceID(),
 		TraceSegmentId: h.Trace.TraceSegmentID(),
 		SpanId:         h.Trace.SpanID(),
-		Type:           h.Trace.Provider().Type,
+		Type:           h.Trace.Provider().SpanAttachType,
 	}
 	return append(attaches, event)
 }
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/reader.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/reader.go
index 32d5fa1..e4aac3f 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/reader.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/reader.go
@@ -28,12 +28,10 @@ import (
 	"strings"
 
 	"github.com/apache/skywalking-rover/pkg/logger"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	"golang.org/x/net/html/charset"
-
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 )
 
 var (
@@ -103,7 +101,7 @@ func (m *MessageOpt) EndTime() uint64 {
 	return m.BodyBuffer().LastSocketBuffer().EndTime()
 }
 
-func (m *MessageOpt) Direction() events.SocketDataDirection {
+func (m *MessageOpt) Direction() enums.SocketDataDirection {
 	return m.HeaderBuffer().FirstSocketBuffer().Direction()
 }
 
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/request.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/request.go
index 9990414..8791611 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/request.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/request.go
@@ -25,8 +25,8 @@ import (
 	"net/url"
 	"strings"
 
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 type Request struct {
@@ -56,7 +56,7 @@ func (r *Request) Original() *http.Request {
 	return r.original
 }
 
-//nolint
+// nolint
 func ReadRequest(buf *buffer.Buffer, readBody bool) (*Request, enums.ParseResult, error) {
 	bufReader := bufio.NewReader(buf)
 	tp := textproto.NewReader(bufReader)
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/response.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/response.go
index fd13c34..966edb8 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/response.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader/response.go
@@ -25,8 +25,8 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/buffer"
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/enums"
+	"github.com/apache/skywalking-rover/pkg/tools/buffer"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 )
 
 type Response struct {
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/http1/sampling.go b/pkg/profiling/task/network/analyze/layer7/protocols/http1/sampling.go
index ae26d50..efd9f93 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/http1/sampling.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/http1/sampling.go
@@ -28,9 +28,9 @@ import (
 	"github.com/apache/skywalking-rover/pkg/process/api"
 	profiling "github.com/apache/skywalking-rover/pkg/profiling/task/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
-	protocol "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/http1/reader"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/metrics"
+	protocol "github.com/apache/skywalking-rover/pkg/tools/tracing"
 )
 
 const (
diff --git a/pkg/profiling/task/network/analyze/layer7/protocols/protocols.go b/pkg/profiling/task/network/analyze/layer7/protocols/protocols.go
index 8dbe6c1..f26826b 100644
--- a/pkg/profiling/task/network/analyze/layer7/protocols/protocols.go
+++ b/pkg/profiling/task/network/analyze/layer7/protocols/protocols.go
@@ -24,6 +24,7 @@ import (
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
 	protocol "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/base"
 	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/layer7/protocols/http1"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 
 	"golang.org/x/net/context"
 )
@@ -46,11 +47,11 @@ func init() {
 
 type Analyzer struct {
 	ctx       protocol.Context
-	protocols map[events.ConnectionProtocol]*protocol.ProtocolAnalyzer
+	protocols map[enums.ConnectionProtocol]*protocol.ProtocolAnalyzer
 }
 
 func NewAnalyzer(ctx protocol.Context, config *profiling.TaskConfig) *Analyzer {
-	protocols := make(map[events.ConnectionProtocol]*protocol.ProtocolAnalyzer)
+	protocols := make(map[enums.ConnectionProtocol]*protocol.ProtocolAnalyzer)
 	for _, r := range registerProtocols {
 		p := r()
 		p.Init(config)
@@ -102,18 +103,18 @@ func (a *Analyzer) ReceiveSocketClose(event *events.SocketCloseEvent) {
 }
 
 type ProtocolMetrics struct {
-	data map[events.ConnectionProtocol]protocol.Metrics
+	data map[enums.ConnectionProtocol]protocol.Metrics
 }
 
 func NewProtocolMetrics() *ProtocolMetrics {
-	metrics := make(map[events.ConnectionProtocol]protocol.Metrics)
+	metrics := make(map[enums.ConnectionProtocol]protocol.Metrics)
 	for _, p := range defaultInstances {
 		metrics[p.Protocol()] = p.GenerateMetrics()
 	}
 	return &ProtocolMetrics{data: metrics}
 }
 
-func (m *ProtocolMetrics) GetProtocolMetrics(p events.ConnectionProtocol) protocol.Metrics {
+func (m *ProtocolMetrics) GetProtocolMetrics(p enums.ConnectionProtocol) protocol.Metrics {
 	return m.data[p]
 }
 
diff --git a/pkg/tools/btf/linker.go b/pkg/tools/btf/linker.go
index 66ef34b..51b7d1b 100644
--- a/pkg/tools/btf/linker.go
+++ b/pkg/tools/btf/linker.go
@@ -132,6 +132,9 @@ func (m *Linker) AddSysCall(call string, enter, exit *ebpf.Program) {
 }
 
 func (m *Linker) AddSysCallWithKProbe(call string, linkK LinkFunc, p *ebpf.Program) {
+	if p == nil {
+		return
+	}
 	kprobe, err := linkK(syscallPrefix+call, p, nil)
 
 	if err != nil {
diff --git a/pkg/profiling/task/network/analyze/buffer/buffer.go b/pkg/tools/buffer/buffer.go
similarity index 68%
rename from pkg/profiling/task/network/analyze/buffer/buffer.go
rename to pkg/tools/buffer/buffer.go
index 8b5ed98..45e518d 100644
--- a/pkg/profiling/task/network/analyze/buffer/buffer.go
+++ b/pkg/tools/buffer/buffer.go
@@ -20,12 +20,11 @@ package buffer
 import (
 	"container/list"
 	"errors"
-	"fmt"
 	"io"
 	"sync"
 	"time"
 
-	"github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/events"
+	"github.com/apache/skywalking-rover/pkg/tools/enums"
 	"github.com/apache/skywalking-rover/pkg/tools/host"
 )
 
@@ -33,6 +32,41 @@ var (
 	ErrNotComplete = errors.New("socket: not complete event")
 )
 
+type SocketDataBuffer interface {
+	// GenerateConnectionID for identity the buffer belong which connection
+	GenerateConnectionID() string
+	// BufferData of the buffer
+	BufferData() []byte
+	// TotalSize of socket data, the data may exceed the size of the BufferData()
+	TotalSize() uint64
+	// Direction of the data, send or receive
+	Direction() enums.SocketDataDirection
+	// BufferStartPosition the buffer start index
+	BufferStartPosition() int
+	// BufferLen the buffer data length
+	BufferLen() int
+	// DataID data id of the buffer
+	DataID() uint64
+	// DataSequence the data sequence under same data id
+	DataSequence() int
+	// IsStart this buffer is start of the same data id
+	IsStart() bool
+	// IsFinished this buffer is finish of the same data id
+	IsFinished() bool
+	// HaveReduceDataAfterChunk check have reduced data after current buffer
+	HaveReduceDataAfterChunk() bool
+
+	// StartTime the data start timestamp
+	StartTime() uint64
+	// EndTime the data end timestamp
+	EndTime() uint64
+}
+
+type SocketDataDetail interface {
+	// DataID data id of the buffer
+	DataID() uint64
+}
+
 type Buffer struct {
 	dataEvents   *list.List
 	detailEvents *list.List
@@ -48,6 +82,24 @@ type Buffer struct {
 	latestExpiredDataID uint64
 }
 
+type SocketDataEventLimited struct {
+	SocketDataBuffer
+	From int
+	Size int
+}
+
+func (s *SocketDataEventLimited) BufferData() []byte {
+	return s.SocketDataBuffer.BufferData()[s.From:s.Size]
+}
+
+func (s *SocketDataEventLimited) BufferLen() int {
+	return s.Size - s.From
+}
+
+func (s *SocketDataEventLimited) BufferStartPosition() int {
+	return s.From
+}
+
 type Position struct {
 	// element of the event list
 	element *list.Element
@@ -55,10 +107,16 @@ type Position struct {
 	bufIndex int
 }
 
-func (p *Position) String() string {
-	buffer := p.element.Value.(events.SocketDataBuffer)
-	return fmt.Sprintf("data id: %d, sequence: %d, buffer index: %d",
-		buffer.DataID(), buffer.DataSequence(), p.bufIndex)
+func (p *Position) Clone() *Position {
+	return &Position{element: p.element, bufIndex: p.bufIndex}
+}
+
+func (p *Position) DataID() uint64 {
+	return p.element.Value.(SocketDataBuffer).DataID()
+}
+
+func (p *Position) Seq() int {
+	return p.element.Value.(SocketDataBuffer).DataSequence()
 }
 
 func NewBuffer() *Buffer {
@@ -69,9 +127,9 @@ func NewBuffer() *Buffer {
 	}
 }
 
-func (r *Buffer) FindFirstDataBuffer(dataID uint64) events.SocketDataBuffer {
+func (r *Buffer) FindFirstDataBuffer(dataID uint64) SocketDataBuffer {
 	for e := r.dataEvents.Front(); e != nil; e = e.Next() {
-		cur := e.Value.(events.SocketDataBuffer)
+		cur := e.Value.(SocketDataBuffer)
 		if cur.DataID() == dataID {
 			return cur
 		}
@@ -83,6 +141,16 @@ func (r *Buffer) Position() *Position {
 	return r.current.Clone()
 }
 
+func (r *Buffer) Clean() {
+	r.eventLocker.Lock()
+	defer r.eventLocker.Unlock()
+
+	r.dataEvents = list.New()
+	r.detailEvents = list.New()
+	r.head = nil
+	r.current = nil
+}
+
 func (r *Buffer) Slice(validated bool, start, end *Position) *Buffer {
 	dataEvents := list.New()
 	detailEvents := list.New()
@@ -91,7 +159,7 @@ func (r *Buffer) Slice(validated bool, start, end *Position) *Buffer {
 		// found first matches detail event
 		if detailEvents.Len() == 0 || firstDetailElement == nil {
 			for e := r.detailEvents.Front(); e != nil; e = e.Next() {
-				if e.Value.(*events.SocketDetailEvent).DataID >= nextElement.Value.(events.SocketDataBuffer).DataID() {
+				if e.Value.(SocketDataDetail).DataID() >= nextElement.Value.(SocketDataBuffer).DataID() {
 					detailEvents.PushBack(e.Value)
 					firstDetailElement = e
 					break
@@ -100,20 +168,20 @@ func (r *Buffer) Slice(validated bool, start, end *Position) *Buffer {
 		}
 		dataEvents.PushBack(nextElement.Value)
 	}
-	lastBuffer := end.element.Value.(events.SocketDataBuffer)
-	dataEvents.PushBack(&events.SocketDataEventLimited{SocketDataBuffer: lastBuffer, Size: end.bufIndex})
+	lastBuffer := end.element.Value.(SocketDataBuffer)
+	dataEvents.PushBack(&SocketDataEventLimited{SocketDataBuffer: lastBuffer, Size: end.bufIndex})
 
 	// if the first detail element been found, append the details until the last buffer data id
 	if firstDetailElement == nil {
 		for e := r.detailEvents.Front(); e != nil; e = e.Next() {
-			if e.Value.(*events.SocketDetailEvent).DataID == lastBuffer.DataID() {
+			if e.Value.(SocketDataDetail).DataID() == lastBuffer.DataID() {
 				detailEvents.PushBack(e.Value)
 				break
 			}
 		}
-	} else if firstDetailElement != nil && firstDetailElement.Value.(*events.SocketDetailEvent).DataID != lastBuffer.DataID() {
+	} else if firstDetailElement != nil && firstDetailElement.Value.(SocketDataDetail).DataID() != lastBuffer.DataID() {
 		for tmp := firstDetailElement.Next(); tmp != nil; tmp = tmp.Next() {
-			if tmp.Value.(*events.SocketDetailEvent).DataID > lastBuffer.DataID() {
+			if tmp.Value.(SocketDataDetail).DataID() > lastBuffer.DataID() {
 				break
 			}
 			detailEvents.PushBack(tmp.Value)
@@ -136,7 +204,7 @@ func (r *Buffer) Len() int {
 	var result int
 	var startIndex = r.head.bufIndex
 	for e := r.head.element; e != nil; e = e.Next() {
-		result += r.head.element.Value.(events.SocketDataBuffer).BufferLen() - startIndex
+		result += r.head.element.Value.(SocketDataBuffer).BufferLen() - startIndex
 		startIndex = 0
 	}
 	return result
@@ -146,18 +214,43 @@ func (r *Buffer) Details() *list.List {
 	return r.detailEvents
 }
 
-func (r *Buffer) FirstSocketBuffer() events.SocketDataBuffer {
+func (r *Buffer) DataSize() int64 {
+	var result int64
+	var headPosition = r.head
+	if headPosition == nil {
+		if !r.PrepareForReading() {
+			return 0
+		}
+		defer func() {
+			r.ResetForLoopReading()
+		}()
+		headPosition = r.head
+	}
+
+	isFirst := true
+	for e := headPosition.element; e != nil; e = e.Next() {
+		if isFirst {
+			result += int64(e.Value.(SocketDataBuffer).BufferLen() - headPosition.bufIndex)
+			isFirst = false
+		} else {
+			result += int64(e.Value.(SocketDataBuffer).BufferLen())
+		}
+	}
+	return result
+}
+
+func (r *Buffer) FirstSocketBuffer() SocketDataBuffer {
 	if r.dataEvents.Len() == 0 {
 		return nil
 	}
-	return r.dataEvents.Front().Value.(events.SocketDataBuffer)
+	return r.dataEvents.Front().Value.(SocketDataBuffer)
 }
 
-func (r *Buffer) LastSocketBuffer() events.SocketDataBuffer {
+func (r *Buffer) LastSocketBuffer() SocketDataBuffer {
 	if r.dataEvents.Len() == 0 {
 		return nil
 	}
-	return r.dataEvents.Back().Value.(events.SocketDataBuffer)
+	return r.dataEvents.Back().Value.(SocketDataBuffer)
 }
 
 // DetectNotSendingLastPosition detect the buffer contains not sending data: the BPF limited socket data count
@@ -167,7 +260,7 @@ func (r *Buffer) DetectNotSendingLastPosition() *Position {
 	}
 
 	for e := r.dataEvents.Front(); e != nil; e = e.Next() {
-		buf := e.Value.(events.SocketDataBuffer)
+		buf := e.Value.(SocketDataBuffer)
 		// the buffer is sent finished but still have reduced data not send
 		if buf.IsFinished() && buf.HaveReduceDataAfterChunk() {
 			return &Position{element: e, bufIndex: buf.BufferLen()}
@@ -186,9 +279,12 @@ func CombineSlices(validated bool, buffers ...*Buffer) *Buffer {
 	dataEvents := list.New()
 	detailEvents := list.New()
 	for _, b := range buffers {
+		if b == nil {
+			continue
+		}
 		if b.head.bufIndex > 0 {
-			headBuffer := b.dataEvents.Front().Value.(events.SocketDataBuffer)
-			dataEvents.PushBack(&events.SocketDataEventLimited{SocketDataBuffer: headBuffer,
+			headBuffer := b.dataEvents.Front().Value.(SocketDataBuffer)
+			dataEvents.PushBack(&SocketDataEventLimited{SocketDataBuffer: headBuffer,
 				From: b.head.bufIndex, Size: headBuffer.BufferLen()})
 			for next := b.dataEvents.Front().Next(); next != nil; next = next.Next() {
 				dataEvents.PushBack(next.Value)
@@ -244,7 +340,7 @@ func (r *Buffer) OffsetPosition(offset int) *Position {
 	var curIndex = r.current.bufIndex
 	for ; curEle != nil; curEle = nextElement(curEle) {
 		nextOffset := curIndex + offset
-		bufferLen := curEle.Value.(events.SocketDataBuffer).BufferLen()
+		bufferLen := curEle.Value.(SocketDataBuffer).BufferLen()
 		if nextOffset >= 0 && nextOffset < bufferLen {
 			curIndex += offset
 			break
@@ -260,7 +356,7 @@ func (r *Buffer) OffsetPosition(offset int) *Position {
 				curEle = next
 				break
 			}
-			curIndex = curEle.Value.(events.SocketDataBuffer).BufferLen()
+			curIndex = curEle.Value.(SocketDataBuffer).BufferLen()
 		}
 	}
 
@@ -282,12 +378,12 @@ func (r *Buffer) Read(p []byte) (n int, err error) {
 		return n, nil
 	}
 
-	curEvent := element.Value.(events.SocketDataBuffer)
+	curEvent := element.Value.(SocketDataBuffer)
 	next := r.nextElement(element)
 	if next == nil {
 		return 0, io.EOF
 	}
-	nextEvent := next.Value.(events.SocketDataBuffer)
+	nextEvent := next.Value.(SocketDataBuffer)
 
 	var shouldRead = false
 	if r.validated {
@@ -311,7 +407,7 @@ func (r *Buffer) Read(p []byte) (n int, err error) {
 
 func (r *Buffer) ReadFromCurrent(p []byte) (element *list.Element, n int) {
 	element = r.current.element
-	curEvent := element.Value.(events.SocketDataBuffer)
+	curEvent := element.Value.(SocketDataBuffer)
 	residueSize := curEvent.BufferLen() - r.current.bufIndex
 	if residueSize > 0 {
 		readLen := len(p)
@@ -326,23 +422,37 @@ func (r *Buffer) ReadFromCurrent(p []byte) (element *list.Element, n int) {
 	return element, 0
 }
 
+func (r *Buffer) ReadUntilBufferFull(data []byte) error {
+	reduceLen := len(data)
+	currentIndex := 0
+	for reduceLen > 0 {
+		readCount, err := r.Read(data[:reduceLen])
+		if err != nil {
+			return err
+		}
+		reduceLen -= readCount
+		currentIndex += readCount
+	}
+	return nil
+}
+
 func (r *Buffer) Merge(other *Buffer) {
 	if other == nil {
 		return
 	}
 	for e := other.dataEvents.Front(); e != nil; e = e.Next() {
-		if v, ok := e.Value.(*events.SocketDataUploadEvent); ok && v != nil {
+		if v, ok := e.Value.(SocketDataBuffer); ok && v != nil {
 			r.AppendDataEvent(v)
 		}
 	}
 	for e := other.detailEvents.Front(); e != nil; e = e.Next() {
-		if v, ok := e.Value.(*events.SocketDetailEvent); ok && v != nil {
+		if v, ok := e.Value.(SocketDataDetail); ok && v != nil {
 			r.AppendDetailEvent(v)
 		}
 	}
 }
 
-func (r *Buffer) read0(currentElement *list.Element, currentBuffer events.SocketDataBuffer, p []byte) (n int, err error) {
+func (r *Buffer) read0(currentElement *list.Element, currentBuffer SocketDataBuffer, p []byte) (n int, err error) {
 	readLen := len(p)
 	if currentBuffer.BufferLen() < readLen {
 		readLen = currentBuffer.BufferLen()
@@ -356,7 +466,7 @@ func (r *Buffer) read0(currentElement *list.Element, currentBuffer events.Socket
 
 // IsCurrentPacketReadFinished means to validate the current reading package is reading finished
 func (r *Buffer) IsCurrentPacketReadFinished() bool {
-	return r.current.bufIndex == r.current.element.Value.(events.SocketDataBuffer).BufferLen()
+	return r.current.bufIndex == r.current.element.Value.(SocketDataBuffer).BufferLen()
 }
 
 func (r *Buffer) ResetForLoopReading() {
@@ -382,20 +492,26 @@ func (r *Buffer) PrepareForReading() bool {
 	return true
 }
 
+// nolint
 func (r *Buffer) RemoveReadElements() bool {
 	r.eventLocker.Lock()
 	defer r.eventLocker.Unlock()
 
 	// delete until the last data id
 	if r.head.element != nil && r.current.element != nil {
-		firstDataID := r.head.element.Value.(events.SocketDataBuffer).DataID()
-		lastDataID := r.current.element.Value.(events.SocketDataBuffer).DataID()
+		firstDataID := r.head.element.Value.(SocketDataBuffer).DataID()
+		currentBuffer := r.current.element.Value.(SocketDataBuffer)
+		lastDataID := currentBuffer.DataID()
 		startDelete := false
 		for e := r.detailEvents.Front(); e != nil; {
-			event := e.Value.(*events.SocketDetailEvent)
-			if !startDelete && event.DataID >= firstDataID && event.DataID <= lastDataID {
+			event := e.Value.(SocketDataDetail)
+			if firstDataID == lastDataID && currentBuffer.BufferLen() != r.current.bufIndex {
+				// current buffer is not finished, so the detail cannot be deleted
+				break
+			}
+			if !startDelete && event.DataID() >= firstDataID && event.DataID() <= lastDataID {
 				startDelete = true
-			} else if startDelete && event.DataID > lastDataID {
+			} else if startDelete && event.DataID() > lastDataID {
 				// out of the data id, just break
 				break
 			}
@@ -412,17 +528,25 @@ func (r *Buffer) RemoveReadElements() bool {
 
... 433 lines suppressed ...