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);
}
}