From d0ef96780b2cf8b309a716487aa99c94e81e27c1 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 2 Apr 2024 09:55:07 -0400 Subject: [PATCH] MT#55283 move interface stats to shm Use the kernel/user shared memory to keep track of interface stats. This eliminates the need to update the userspace stats counters with the values from the kernel, and vice versa when updating the kernel streams. Add a function to reverse map userspace mapped memory address to kernel space addresses. Change-Id: Iaa5f9488061a12103e57faf27b3979521778cea8 --- daemon/media_socket.c | 4 +-- include/kernel.h | 1 + kernel-module/common_stats.h | 6 +++++ kernel-module/xt_RTPENGINE.c | 47 +++++++++++++++++++++++++++++++++--- kernel-module/xt_RTPENGINE.h | 6 +++++ lib/socket.c | 1 + 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/daemon/media_socket.c b/daemon/media_socket.c index cbb5a47a8..cde5ec55d 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -53,8 +53,6 @@ else \ diff_ ## x ## _ ## io = (ke)->x - ks_val; \ atomic64_add(&ps->stats_ ## io.x, diff_ ## x ## _ ## io); \ - if (ps->selected_sfd) \ - atomic64_add_na(&ps->selected_sfd->local_intf->stats->io.x, diff_ ## x ## _ ## io); \ RTPE_STATS_ADD(x ## _kernel, diff_ ## x ## _ ## io); \ } while (0) @@ -1487,6 +1485,7 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out } __re_address_translate_ep(&reti->local, &stream->selected_sfd->socket.local); + reti->iface_stats = stream->selected_sfd->local_intf->stats; reti->rtcp_mux = MEDIA_ISSET(media, RTCP_MUX); reti->rtcp = PS_ISSET(stream, RTCP); reti->dtls = MEDIA_ISSET(media, DTLS); @@ -1622,6 +1621,7 @@ output: __re_address_translate_ep(&redi->output.dst_addr, &sink->endpoint); __re_address_translate_ep(&redi->output.src_addr, &sink->selected_sfd->socket.local); + redi->output.iface_stats = sink->selected_sfd->local_intf->stats; if (reti->track_ssrc) { for (unsigned int u = 0; u < G_N_ELEMENTS(stream->ssrc_in); u++) { diff --git a/include/kernel.h b/include/kernel.h index 5d875b18b..0536ee1ed 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -6,6 +6,7 @@ #include #include "containers.h" +#include "auxlib.h" #include "xt_RTPENGINE.h" diff --git a/kernel-module/common_stats.h b/kernel-module/common_stats.h index e0db7dd95..d4571de04 100644 --- a/kernel-module/common_stats.h +++ b/kernel-module/common_stats.h @@ -2,6 +2,12 @@ #define _RTPE_COMMON_STATS_H_ +#ifdef __KERNEL__ +typedef atomic64_t atomic64; +static_assert(sizeof(atomic64_t) == sizeof(int64_t), "atomic64_t != int64_t"); +#endif + + struct interface_counter_stats_dir { #define F(n) atomic64 n; #include "interface_counter_stats_fields_dir.inc" diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 3a87ce4bc..3f5d2abf8 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -2008,6 +2008,26 @@ static int is_valid_address(const struct re_address *rea) { return 1; } +static void vm_mmap_close(struct vm_area_struct *vma) { +} +static const struct vm_operations_struct vm_mmap_ops = { + .close = vm_mmap_close, +}; + +static void *shm_map_resolve(void *p, size_t size) { + struct vm_area_struct *vma; + // XXX is there a better way to map this to the kernel address? + vma = vma_lookup(current->mm, (unsigned long) p); + if (!vma) + return NULL; + if (!vma->vm_private_data) + return NULL; + if ((unsigned long) p + size > vma->vm_end || (unsigned long) p + size < vma->vm_start) + return NULL; + if (vma->vm_ops != &vm_mmap_ops) + return NULL; + return vma->vm_private_data + ((unsigned long) p - (unsigned long) vma->vm_start); +} @@ -2404,6 +2424,7 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i int err; unsigned long flags; unsigned int u; + struct interface_stats_block *iface_stats; /* validation */ @@ -2424,6 +2445,10 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i if (validate_srtp(&i->decrypt)) return -EINVAL; + iface_stats = shm_map_resolve(i->iface_stats, sizeof(*iface_stats)); + if (!iface_stats) + return -EFAULT; + DBG("Creating new target\n"); /* initializing */ @@ -2444,6 +2469,7 @@ static int table_new_target(struct rtpengine_table *t, struct rtpengine_target_i for (u = 0; u < RTPE_NUM_SSRC_TRACKING; u++) g->ssrc_stats[u].lost_bits = -1; rwlock_init(&g->outputs_lock); + g->target.iface_stats = iface_stats; if (i->num_destinations) { err = -ENOMEM; @@ -2562,6 +2588,7 @@ static int table_add_destination(struct rtpengine_table *t, struct rtpengine_des unsigned long flags; int err; struct rtpengine_target *g; + struct interface_stats_block *iface_stats; // validate input @@ -2574,6 +2601,10 @@ static int table_add_destination(struct rtpengine_table *t, struct rtpengine_des if (validate_srtp(&i->output.encrypt)) return -EINVAL; + iface_stats = shm_map_resolve(i->output.iface_stats, sizeof(*iface_stats)); + if (!iface_stats) + return -EFAULT; + g = get_target(t, &i->local); if (!g) return -ENOENT; @@ -2597,6 +2628,7 @@ static int table_add_destination(struct rtpengine_table *t, struct rtpengine_des goto out; g->outputs[i->num].output = i->output; + g->outputs[i->num].output.iface_stats = iface_stats; // init crypto stuff lock free: the "output" is already filled so we // know it's there, but outputs_unfilled hasn't been decreased yet, so @@ -2734,8 +2766,6 @@ static ssize_t proc_main_control_write(struct file *file, const char __user *buf } - - static int proc_control_mmap(struct file *file, struct vm_area_struct *vma) { size_t size, order; unsigned long pfn; @@ -2801,6 +2831,7 @@ static int proc_control_mmap(struct file *file, struct vm_area_struct *vma) { pfn = virt_to_phys(pages) >> PAGE_SHIFT; vma->vm_private_data = pages; // remember kernel-space address + vma->vm_ops = &vm_mmap_ops; ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot); @@ -5458,6 +5489,7 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct sk_buff *oskb, if (!skb2) { log_err("out of memory while creating skb copy"); atomic64_inc(&g->stats_in.errors); + atomic64_inc(&g->target.iface_stats->in.errors); continue; } skb_gso_reset(skb2); @@ -5474,11 +5506,15 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct sk_buff *oskb, err = send_proxy_packet_output(skb2, g, rtp_pt_idx, o, &rtp2, ssrc_idx, par); if (err) { atomic64_inc(&g->stats_in.errors); + atomic64_inc(&g->target.iface_stats->in.errors); atomic64_inc(&o->stats_out.errors); + atomic64_inc(&o->output.iface_stats->out.errors); } else { atomic64_inc(&o->stats_out.packets); atomic64_add(datalen_out, &o->stats_out.bytes); + atomic64_inc(&o->output.iface_stats->out.packets); + atomic64_add(datalen_out, &o->output.iface_stats->out.bytes); } } @@ -5488,6 +5524,8 @@ do_stats: atomic64_inc(&g->stats_in.packets); atomic64_add(datalen, &g->stats_in.bytes); + atomic64_inc(&g->target.iface_stats->in.packets); + atomic64_add(datalen, &g->target.iface_stats->in.bytes); if (rtp_pt_idx >= 0) { atomic64_inc(&g->rtp_stats[rtp_pt_idx].packets); @@ -5495,8 +5533,10 @@ do_stats: } else if (rtp_pt_idx == -2) /* not RTP */ ; - else if (rtp_pt_idx == -1) + else if (rtp_pt_idx == -1) { atomic64_inc(&g->stats_in.errors); + atomic64_inc(&g->target.iface_stats->in.errors); + } target_put(g); table_put(t); @@ -5508,6 +5548,7 @@ do_stats: out_error: log_err("x_tables action failed: %s", errstr); atomic64_inc(&g->stats_in.errors); + atomic64_inc(&g->target.iface_stats->in.errors); out: target_put(g); out_no_target: diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index 650a8ec14..9931c1384 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -2,6 +2,8 @@ #define XT_RTPPROXY_H +#include "common_stats.h" + #define RTPE_NUM_PAYLOAD_TYPES 32 #define RTPE_MAX_FORWARD_DESTINATIONS 32 @@ -116,6 +118,8 @@ struct rtpengine_target_info { struct rtpengine_pt_input pt_input[RTPE_NUM_PAYLOAD_TYPES]; /* must be sorted */ unsigned int num_payload_types; + struct interface_stats_block *iface_stats; // for ingress stats + unsigned int rtcp_mux:1, dtls:1, stun:1, @@ -141,6 +145,8 @@ struct rtpengine_output_info { uint32_t seq_offset[RTPE_NUM_SSRC_TRACKING]; // Rewrite output seq struct rtpengine_pt_output pt_output[RTPE_NUM_PAYLOAD_TYPES]; // same indexes as pt_input + struct interface_stats_block *iface_stats; // for egress stats + unsigned char tos; unsigned int ssrc_subst:1; }; diff --git a/lib/socket.c b/lib/socket.c index 1efdaa4a5..382be607e 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -8,6 +8,7 @@ #include #include #include "str.h" +#include "auxlib.h" #include "xt_RTPENGINE.h" #include "log.h"