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
pull/1826/head
Richard Fuchs 1 year ago
parent 7f07a5d24b
commit d0ef96780b

@ -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++) {

@ -6,6 +6,7 @@
#include <netinet/in.h>
#include "containers.h"
#include "auxlib.h"
#include "xt_RTPENGINE.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"

@ -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:

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

@ -8,6 +8,7 @@
#include <netinet/udp.h>
#include <sys/socket.h>
#include "str.h"
#include "auxlib.h"
#include "xt_RTPENGINE.h"
#include "log.h"

Loading…
Cancel
Save