diff --git a/daemon/call.c b/daemon/call.c index ab986833a..27c1da265 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -507,6 +507,30 @@ destroy: } +// reverse of count_stream_stats_userspace() +static void count_stream_stats_kernel(struct packet_stream *ps) { + if (!PS_ISSET(ps, RTP)) + return; + if (bf_set(&ps->stats_flags, PS_STATS_KERNEL)) + return; // flag was already set, nothing to do + + if (bf_isset(&ps->stats_flags, PS_STATS_USERSPACE)) { + // mixed stream. count as only mixed stream. + if (bf_clear(&ps->stats_flags, PS_STATS_KERNEL_COUNTED)) + RTPE_GAUGE_DEC(kernel_only_streams); + if (bf_clear(&ps->stats_flags, PS_STATS_USERSPACE_COUNTED)) + RTPE_GAUGE_DEC(userspace_streams); + if (!bf_set(&ps->stats_flags, PS_STATS_MIXED_COUNTED)) + RTPE_GAUGE_INC(kernel_user_streams); + } + else { + // kernel-only (for now). count it. + if (!bf_set(&ps->stats_flags, PS_STATS_KERNEL_COUNTED)) + RTPE_GAUGE_INC(kernel_only_streams); + } +} + + #define DS(x) do { \ uint64_t ks_val; \ ks_val = atomic64_get(&ps->kernel_stats.x); \ @@ -582,8 +606,10 @@ void call_timer(void *ptr) { DS(errors); - if (ke->stats.packets != atomic64_get(&ps->kernel_stats.packets)) + if (ke->stats.packets != atomic64_get(&ps->kernel_stats.packets)) { atomic64_set(&ps->last_packet, rtpe_now.tv_sec); + count_stream_stats_kernel(ps); + } ps->in_tos_tclass = ke->stats.in_tos; diff --git a/daemon/media_socket.c b/daemon/media_socket.c index c78333eba..89cea61ea 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1115,6 +1115,18 @@ static int __rtp_stats_pt_sort(const void *ap, const void *bp) { } +static void reset_ps_kernel_stats(struct packet_stream *ps) { + if (bf_clear(&ps->stats_flags, PS_STATS_KERNEL_COUNTED)) + RTPE_GAUGE_DEC(kernel_only_streams); + if (bf_clear(&ps->stats_flags, PS_STATS_USERSPACE_COUNTED)) + RTPE_GAUGE_DEC(userspace_streams); + if (bf_clear(&ps->stats_flags, PS_STATS_MIXED_COUNTED)) + RTPE_GAUGE_DEC(kernel_user_streams); + + bf_clear(&ps->stats_flags, PS_STATS_KERNEL | PS_STATS_USERSPACE); +} + + /* called with in_lock held */ // sink_handler can be NULL static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *outputs, @@ -1296,6 +1308,9 @@ void kernelize(struct packet_stream *stream) { if (PS_ISSET(stream, KERNELIZED)) return; + + reset_ps_kernel_stats(stream); + if (call->recording != NULL && !selected_recording_method->kernel_support) goto no_kernel; if (!kernel.is_wanted) @@ -1426,6 +1441,8 @@ static void __stream_update_stats(struct packet_stream *ps, int have_in_lock) { void __unkernelize(struct packet_stream *p) { struct re_address rea; + reset_ps_kernel_stats(p); + if (!p->selected_sfd) return; @@ -2180,6 +2197,29 @@ static int media_packet_queue_dup(GQueue *q) { return 0; } +// reverse of count_stream_stats_kernel() +static void count_stream_stats_userspace(struct packet_stream *ps) { + if (!PS_ISSET(ps, RTP)) + return; + if (bf_set(&ps->stats_flags, PS_STATS_USERSPACE)) + return; // flag was already set, nothing to do + + if (bf_isset(&ps->stats_flags, PS_STATS_KERNEL)) { + // mixed stream. count as only mixed stream. + if (bf_clear(&ps->stats_flags, PS_STATS_USERSPACE_COUNTED)) + RTPE_GAUGE_DEC(userspace_streams); + if (bf_clear(&ps->stats_flags, PS_STATS_KERNEL_COUNTED)) + RTPE_GAUGE_DEC(kernel_only_streams); + if (!bf_set(&ps->stats_flags, PS_STATS_MIXED_COUNTED)) + RTPE_GAUGE_INC(kernel_user_streams); + } + else { + // userspace-only (for now). count it. + if (!bf_set(&ps->stats_flags, PS_STATS_USERSPACE_COUNTED)) + RTPE_GAUGE_INC(userspace_streams); + } +} + /* called lock-free */ static int stream_packet(struct packet_handler_ctx *phc) { @@ -2295,6 +2335,8 @@ static int stream_packet(struct packet_handler_ctx *phc) { RTPE_STATS_INC(packets_user); RTPE_STATS_ADD(bytes_user, phc->s.len); + count_stream_stats_userspace(phc->mp.stream); + int address_check = media_packet_address_check(phc); if (address_check) goto drop; diff --git a/daemon/statistics.c b/daemon/statistics.c index 46a51770b..e2d072276 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -371,6 +371,21 @@ GQueue *statistics_gather_metrics(void) { atomic64_get(&rtpe_stats.intv.errors_user) + atomic64_get(&rtpe_stats.intv.errors_kernel)); + METRIC("media_userspace", "Userspace-only media streams", UINT64F, UINT64F, + atomic64_get(&rtpe_stats_gauge.userspace_streams)); + PROM("mediastreams", "gauge"); + PROMLAB("type=\"userspace\""); + + METRIC("media_kernel", "Kernel-only media streams", UINT64F, UINT64F, + atomic64_get(&rtpe_stats_gauge.kernel_only_streams)); + PROM("mediastreams", "gauge"); + PROMLAB("type=\"kernel\""); + + METRIC("media_mixed", "Mixed kernel/userspace media streams", UINT64F, UINT64F, + atomic64_get(&rtpe_stats_gauge.kernel_user_streams)); + PROM("mediastreams", "gauge"); + PROMLAB("type=\"mixed\""); + num_sessions = atomic64_get(&rtpe_stats.ax.managed_sess); long long avg_us = num_sessions ? atomic64_get(&rtpe_stats.ax.call_duration) / num_sessions : 0; timeval_from_us(&avg, avg_us); diff --git a/include/call.h b/include/call.h index 62d36e588..0cbf79769 100644 --- a/include/call.h +++ b/include/call.h @@ -149,6 +149,13 @@ enum { #define PS_FLAG_PIERCE_NAT 0x08000000 #define PS_FLAG_NAT_WAIT 0x10000000 +// packet_stream stats_flags +#define PS_STATS_USERSPACE 0x00000001 +#define PS_STATS_KERNEL 0x00000002 +#define PS_STATS_USERSPACE_COUNTED 0x00000004 +#define PS_STATS_KERNEL_COUNTED 0x00000008 +#define PS_STATS_MIXED_COUNTED 0x00000010 + /* struct call_media */ #define MEDIA_FLAG_INITIALIZED 0x00010000 #define MEDIA_FLAG_ASYMMETRIC SHARED_FLAG_ASYMMETRIC @@ -319,6 +326,7 @@ struct packet_stream { atomic64 last_packet; GHashTable *rtp_stats; /* LOCK: call->master_lock */ struct rtp_stats *rtp_stats_cache; + unsigned int stats_flags; #if RTP_LOOP_PROTECT /* LOCK: in_lock: */ diff --git a/include/gauge_stats_fields.inc b/include/gauge_stats_fields.inc index 34bedbac5..a26b3edf3 100644 --- a/include/gauge_stats_fields.inc +++ b/include/gauge_stats_fields.inc @@ -5,3 +5,6 @@ F(ipv4_sessions) F(ipv6_sessions) F(mixed_sessions) FdA(ng_command_times, NGC_COUNT) +F(userspace_streams) +F(kernel_only_streams) +F(kernel_user_streams) diff --git a/t/test-stats.c b/t/test-stats.c index 8d43681ab..d2d5e6c65 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -312,6 +312,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -1135,6 +1150,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -1955,6 +1985,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -2788,6 +2833,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -3616,6 +3676,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -4439,6 +4514,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n" @@ -5264,6 +5354,21 @@ int main(void) { "errorrate\n" "0\n" "0\n" + "Userspace-only media streams\n" + "media_userspace\n" + "0\n" + "0\n" + "type=\"userspace\"\n" + "Kernel-only media streams\n" + "media_kernel\n" + "0\n" + "0\n" + "type=\"kernel\"\n" + "Mixed kernel/userspace media streams\n" + "media_mixed\n" + "0\n" + "0\n" + "type=\"mixed\"\n" "\n" "}\n" "Total statistics (does not include current running sessions):\n"