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 <netinet/in.h> #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 <netinet/udp.h> #include <sys/socket.h> #include "str.h" +#include "auxlib.h" #include "xt_RTPENGINE.h" #include "log.h"