static __always_inline void process_write_data()

in bpf/profiling/network/netmonitor.c [269:386]


static __always_inline void process_write_data(struct pt_regs *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
    __u64 conid = gen_tgid_fd(tgid, args->fd);
    struct active_connection_t *conn = get_or_create_active_conn(ctx, tgid, args->fd, func_name);
    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 connect event is not sent
    if (conn->connect_event_send == false) {
        // if the connection should trace, double check
        if (tgid_should_trace(tgid) == false) {
            return;
        }
        // resent the connection event
        resent_connect_event(ctx, tgid, args->fd, conid, conn);
    }

    // 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, 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;
            }
        }
    }

    // upload the socket detail
    upload_socket_detail(ctx, conid, conn, func_name, args, ssl);

    // upload the socket data if need
    struct upload_data_args *upload_data_args = generate_socket_upload_args();
    if (upload_data_args != NULL) {
        upload_data_args->start_time = args->start_nacs;
        upload_data_args->end_time = curr_nacs;
        upload_data_args->con_id = conid;
        upload_data_args->random_id = conn->random_id;
        upload_data_args->socket_data_id = args->data_id;
        upload_data_args->socket_data_iovec = args->iovec;
        upload_data_args->socket_data_iovlen = args->iovlen;
        upload_data_args->bytes_count = bytes_count;
        upload_data_args->socket_data_buf = args->buf;
        upload_data_args->data_direction = data_direction;
        upload_data_args->connection_protocol = conn->protocol;
        upload_data_args->connection_ssl = conn->ssl;
        upload_data_args->socket_ssl_buffer_force_unfinished = args->ssl_buffer_force_unfinished;
        upload_data_args->connection_skip_data_upload = 0;
        upload_data_args->socket_data_ssl = ssl;
        upload_socket_data(ctx, upload_data_args);
    }

    // add statics when is not ssl(native buffer)
    if (ssl == false) {
        __u64 exe_time = curr_nacs - args->start_nacs;
        if (data_direction == SOCK_DATA_DIRECTION_EGRESS) {
            conn->write_bytes += bytes_count;
            conn->write_count++;
            conn->write_exe_time += exe_time;

            add_to_socket_connection_stats_histogram(conid, conn->random_id, SOCK_DATA_DIRECTION_EGRESS,
                            SOCKET_CONNECTION_STATS_HISTOGRAM_DATA_TYPE_EXE_TIME, exe_time);
        } else {
            conn->read_bytes += bytes_count;
            conn->read_count++;
            conn->read_exe_time += exe_time;

            add_to_socket_connection_stats_histogram(conid, conn->random_id, SOCK_DATA_DIRECTION_INGRESS,
                                    SOCKET_CONNECTION_STATS_HISTOGRAM_DATA_TYPE_EXE_TIME, exe_time);
        }
    }

    // RTT
    if (args->rtt_count > 0) {
        conn->write_rtt_count += args->rtt_count;
        conn->write_rtt_time += args->rtt_time;

        __u64 avg_rtt = args->rtt_time / args->rtt_count;
        add_to_socket_connection_stats_histogram(conid, conn->random_id, SOCK_DATA_DIRECTION_EGRESS,
                SOCKET_CONNECTION_STATS_HISTOGRAM_DATA_TYPE_RTT, avg_rtt);
    }
}