From 6bc7a77e9bd386bf1564e87561e1956011e6cfad Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Thu, 19 Feb 2015 08:45:48 +0100 Subject: [PATCH 1/4] First try of implementation of measureing delay. Will be squashed later. --- daemon/Makefile | 2 +- daemon/call.c | 16 ++++++++++++++++ daemon/call.h | 2 ++ daemon/cli.c | 11 ++++++++--- daemon/graphite.c | 1 + daemon/kernel.c | 15 +++++++++++++++ daemon/main.c | 9 +++++++++ daemon/measuredelay.c | 33 ++++++++++++++++++++++++++++++++ daemon/measuredelay.h | 14 ++++++++++++++ kernel-module/xt_RTPENGINE.c | 37 +++++++++++++++++++++++++++++++----- kernel-module/xt_RTPENGINE.h | 4 ++++ 11 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 daemon/measuredelay.c create mode 100644 daemon/measuredelay.h diff --git a/daemon/Makefile b/daemon/Makefile index 24d0637b6..b1c762f73 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -63,7 +63,7 @@ endif SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \ bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c rtcp.c \ - crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c + crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c measuredelay.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/call.c b/daemon/call.c index 6492a0abb..ec4142bd4 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1344,6 +1344,12 @@ static void callmaster_timer(void *ptr) { DS(bytes); DS(errors); + mutex_lock(&m->statspslock); + ilog(LOG_INFO, "Start time:%llu\n", ke->stats.start.tv_nsec); + m->statsps.start = ke->stats.start; + m->statsps.end = ke->stats.end; + mutex_unlock(&m->statspslock); + mutex_lock(&ps->in_lock); if (ke->stats.packets != ps->kernel_stats.packets) @@ -1353,6 +1359,9 @@ static void callmaster_timer(void *ptr) { ps->kernel_stats.bytes = ke->stats.bytes; ps->kernel_stats.errors = ke->stats.errors; + ps->kernel_stats.start = ke->stats.start; + ps->kernel_stats.end = ke->stats.end; + update = 0; sink = packet_stream_sink(ps); @@ -2375,6 +2384,13 @@ static void unkernelize(struct packet_stream *p) { PS_CLEAR(p, KERNELIZED); } +void timespec_subtract (struct timespec *result, const struct timespec *a, const struct timespec *b) { + long long nanoseconds=0; + nanoseconds = ((long)a->tv_sec - (long long)b->tv_sec) * 1000000000 + ((long long)a->tv_nsec - (long long)b->tv_nsec); + result->tv_sec = nanoseconds/(long long)1000000000; + result->tv_nsec = nanoseconds%(long long)1000000000; +} + void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b) { long microseconds=0; microseconds = ((long)a->tv_sec - (long)b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec); diff --git a/daemon/call.h b/daemon/call.h index 8be512487..1c43d86b7 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -190,6 +190,8 @@ struct stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; + struct timespec start; + struct timespec end; }; struct totalstats { diff --git a/daemon/cli.c b/daemon/cli.c index e6e4300ab..0591ec581 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "poller.h" #include "aux.h" @@ -146,9 +148,10 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m if (PS_ISSET(ps, FALLBACK_RTCP)) continue; - + struct timespec result; + timespec_subtract(&result,&(ps->stats.end),&(ps->stats.start)); printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " - "%llu p, %llu b, %llu e, %llu last_packet\n", + "%llu p, %llu b, %llu e, %llu last_packet, %llu.%9llu delay\n", md->index, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, @@ -156,7 +159,9 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m (unsigned long long) ps->stats.packets, (unsigned long long) ps->stats.bytes, (unsigned long long) ps->stats.errors, - (unsigned long long) ps->last_packet); + (unsigned long long) ps->last_packet, + (unsigned long long) result.tv_sec, + (unsigned long long) result.tv_nsec); ADJUSTLEN(printlen,outbufend,replybuffer); } } diff --git a/daemon/graphite.c b/daemon/graphite.c index f886584af..55b32501d 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -144,3 +144,4 @@ void graphite_loop_run(struct callmaster* callmaster, int seconds) { sleep: usleep(100000); } + diff --git a/daemon/kernel.c b/daemon/kernel.c index 670f5496e..552522c12 100644 --- a/daemon/kernel.c +++ b/daemon/kernel.c @@ -102,6 +102,20 @@ int kernel_del_stream(int fd, u_int16_t p) { return -1; } +int kernel_measure_delay(int fd) { + struct rtpengine_message msg; + int ret; + + ZERO(msg); + msg.cmd = MMG_MEASUREDELAY; + + ret = write(fd, &msg, sizeof(msg)); + if (ret > 0) + return 0; + + ilog(LOG_ERROR, "Failed to delete relay stream from kernel: %s", strerror(errno)); + return -1; +} GList *kernel_list(unsigned int id) { char str[64]; @@ -119,6 +133,7 @@ GList *kernel_list(unsigned int id) { for (;;) { buf = g_slice_alloc(sizeof(*buf)); ret = read(fd, buf, sizeof(*buf)); + if (ret != sizeof(*buf)) break; li = g_list_prepend(li, buf); diff --git a/daemon/main.c b/daemon/main.c index 50da00044..333a71d46 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -27,6 +27,7 @@ #include "call_interfaces.h" #include "cli.h" #include "graphite.h" +#include "measuredelay.h" @@ -629,6 +630,13 @@ static void timer_loop(void *d) { poller_timers_wait_run(p, 100); } +static void measuredelay_loop(void *d) { + struct callmaster *cm = d; + + while (!global_shutdown) + measuredelay_loop_run(cm,1); // time in seconds +} + static void graphite_loop(void *d) { struct callmaster *cm = d; @@ -662,6 +670,7 @@ int main(int argc, char **argv) { thread_create_detach(sighandler, NULL); thread_create_detach(timer_loop, ctx.p); + thread_create_detach(measuredelay_loop, ctx.m); if (graphite_ip) thread_create_detach(graphite_loop, ctx.m); diff --git a/daemon/measuredelay.c b/daemon/measuredelay.c new file mode 100644 index 000000000..846d51817 --- /dev/null +++ b/daemon/measuredelay.c @@ -0,0 +1,33 @@ +/* + * meauredelay.c + * + * Created on: Feb 13, 2015 + * Author: fmetz + */ + +#include "log.h" +#include "call.h" +#include "measuredelay.h" +#include "kernel.h" + +static struct callmaster* cm=0; +static time_t g_now, next_run; + +void measuredelay_loop_run(struct callmaster* callmaster, int seconds) { + + int rc=0; + + g_now = time(NULL); + if (g_now < next_run) + goto sleep; + + next_run = g_now + seconds; + + if (!cm) + cm = callmaster; + + kernel_measure_delay(cm->conf.kernelfd); + +sleep: + usleep(100000); +} diff --git a/daemon/measuredelay.h b/daemon/measuredelay.h new file mode 100644 index 000000000..96f5d7798 --- /dev/null +++ b/daemon/measuredelay.h @@ -0,0 +1,14 @@ +/* + * measuredelay.h + * + * Created on: Feb 13, 2015 + * Author: fmetz + */ + +#ifndef MEASUREDELAY_H_ +#define MEASUREDELAY_H_ + +void measuredelay_loop_run(struct callmaster* callmaster, int seconds); + + +#endif /* MEASUREDELAY_H_ */ diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 8589a02ca..7a134f05e 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -1624,6 +1624,9 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz struct rtpengine_table *t; struct rtpengine_message msg; int err; + int port; + struct rtpengine_target *g; + unsigned long flags; if (buflen != sizeof(msg)) return -EIO; @@ -1661,6 +1664,19 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz goto err; break; + case MMG_MEASUREDELAY: + port=0; + if (t==NULL) + break; + g = find_next_target(t, &port); + while (g != NULL) { + spin_lock_irqsave(&g->stats_lock, flags); + g->stats.measureactive=1; + spin_unlock_irqrestore(&g->stats_lock, flags); + g = find_next_target(t, &port); + } + break; + default: printk(KERN_WARNING "xt_RTPENGINE unimplemented op %u\n", msg.cmd); err = -EINVAL; @@ -1792,6 +1808,8 @@ drop: static int send_proxy_packet(struct sk_buff *skb, struct re_address *src, struct re_address *dst, unsigned char tos) { + printk(KERN_WARNING "xt_RTPENGINE send_proxy_packet\n"); + if (src->family != dst->family) goto drop; @@ -2105,7 +2123,7 @@ static inline int is_dtls(struct sk_buff *skb) { return 1; } -static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src) { +static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src, struct timespec *starttime) { struct udphdr *uh; struct rtpengine_target *g; struct sk_buff *skb2; @@ -2212,8 +2230,15 @@ not_rtp: err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos); + out: spin_lock_irqsave(&g->stats_lock, flags); + if (g->stats.measureactive==1) { + g->stats.start = *starttime; + getnstimeofday(&g->stats.end); + g->stats.measureactive=0; + } + printk(KERN_WARNING "xt_RTPENGINE failed to create /proc entry for ID %llu\n", g->stats.start.tv_nsec); if (err) g->stats.errors++; else { @@ -2254,6 +2279,8 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para struct iphdr *ih; struct rtpengine_table *t; struct re_address src; + struct timespec starttime; + getnstimeofday(&starttime); t = get_table(pinfo->id); if (!t) @@ -2272,8 +2299,7 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET; src.u.ipv4 = ih->saddr; - - return rtpengine46(skb, t, &src); + return rtpengine46(skb, t, &src, &starttime); skip2: kfree_skb(skb); @@ -2296,6 +2322,8 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para struct ipv6hdr *ih; struct rtpengine_table *t; struct re_address src; + struct timespec starttime; + getnstimeofday(&starttime); t = get_table(pinfo->id); if (!t) @@ -2314,8 +2342,7 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET6; memcpy(&src.u.ipv6, &ih->saddr, sizeof(src.u.ipv6)); - - return rtpengine46(skb, t, &src); + return rtpengine46(skb, t, &src, &starttime); skip2: kfree_skb(skb); diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index 5f419a08c..cde73dff2 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -9,6 +9,9 @@ struct rtpengine_stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; + struct timespec start; + struct timespec end; + u_int32_t measureactive; }; struct re_address { @@ -86,6 +89,7 @@ struct rtpengine_message { MMG_ADD, MMG_DEL, MMG_UPDATE, + MMG_MEASUREDELAY, } cmd; struct rtpengine_target_info target; From e0f9c59274fefac6c54bed42ff748c4a56508af4 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Sun, 15 Mar 2015 13:29:46 +0100 Subject: [PATCH 2/4] Implemented stage 1 of measuring delay --- daemon/call.c | 5 ++--- daemon/cli.c | 2 +- kernel-module/xt_RTPENGINE.c | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index ec4142bd4..26a85bfab 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1345,9 +1345,8 @@ static void callmaster_timer(void *ptr) { DS(errors); mutex_lock(&m->statspslock); - ilog(LOG_INFO, "Start time:%llu\n", ke->stats.start.tv_nsec); - m->statsps.start = ke->stats.start; - m->statsps.end = ke->stats.end; + ps->stats.start = m->statsps.start = ke->stats.start; + ps->stats.end = m->statsps.end = ke->stats.end; mutex_unlock(&m->statspslock); mutex_lock(&ps->in_lock); diff --git a/daemon/cli.c b/daemon/cli.c index 0591ec581..4d105c215 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -151,7 +151,7 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m struct timespec result; timespec_subtract(&result,&(ps->stats.end),&(ps->stats.start)); printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " - "%llu p, %llu b, %llu e, %llu last_packet, %llu.%9llu delay\n", + "%llu p, %llu b, %llu e, %llu last_packet, %llu.%09llu delay\n", md->index, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 7a134f05e..506bdf3b1 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -1808,7 +1808,6 @@ drop: static int send_proxy_packet(struct sk_buff *skb, struct re_address *src, struct re_address *dst, unsigned char tos) { - printk(KERN_WARNING "xt_RTPENGINE send_proxy_packet\n"); if (src->family != dst->family) goto drop; @@ -2238,7 +2237,7 @@ out: getnstimeofday(&g->stats.end); g->stats.measureactive=0; } - printk(KERN_WARNING "xt_RTPENGINE failed to create /proc entry for ID %llu\n", g->stats.start.tv_nsec); + if (err) g->stats.errors++; else { From bd24127bce96ee44f72f8c1ac6f45ba551cd0053 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Sun, 15 Mar 2015 13:31:43 +0100 Subject: [PATCH 3/4] Revert "First try of implementation of measureing delay." This reverts commit 6bc7a77e9bd386bf1564e87561e1956011e6cfad. --- daemon/Makefile | 2 +- daemon/call.c | 16 ---------------- daemon/call.h | 2 -- daemon/cli.c | 11 +++-------- daemon/graphite.c | 1 - daemon/kernel.c | 15 --------------- daemon/main.c | 9 --------- daemon/measuredelay.c | 33 -------------------------------- daemon/measuredelay.h | 14 -------------- kernel-module/xt_RTPENGINE.c | 37 +++++------------------------------- kernel-module/xt_RTPENGINE.h | 4 ---- 11 files changed, 9 insertions(+), 135 deletions(-) delete mode 100644 daemon/measuredelay.c delete mode 100644 daemon/measuredelay.h diff --git a/daemon/Makefile b/daemon/Makefile index b1c762f73..24d0637b6 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -63,7 +63,7 @@ endif SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \ bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c rtcp.c \ - crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c measuredelay.c + crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/call.c b/daemon/call.c index ec4142bd4..6492a0abb 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1344,12 +1344,6 @@ static void callmaster_timer(void *ptr) { DS(bytes); DS(errors); - mutex_lock(&m->statspslock); - ilog(LOG_INFO, "Start time:%llu\n", ke->stats.start.tv_nsec); - m->statsps.start = ke->stats.start; - m->statsps.end = ke->stats.end; - mutex_unlock(&m->statspslock); - mutex_lock(&ps->in_lock); if (ke->stats.packets != ps->kernel_stats.packets) @@ -1359,9 +1353,6 @@ static void callmaster_timer(void *ptr) { ps->kernel_stats.bytes = ke->stats.bytes; ps->kernel_stats.errors = ke->stats.errors; - ps->kernel_stats.start = ke->stats.start; - ps->kernel_stats.end = ke->stats.end; - update = 0; sink = packet_stream_sink(ps); @@ -2384,13 +2375,6 @@ static void unkernelize(struct packet_stream *p) { PS_CLEAR(p, KERNELIZED); } -void timespec_subtract (struct timespec *result, const struct timespec *a, const struct timespec *b) { - long long nanoseconds=0; - nanoseconds = ((long)a->tv_sec - (long long)b->tv_sec) * 1000000000 + ((long long)a->tv_nsec - (long long)b->tv_nsec); - result->tv_sec = nanoseconds/(long long)1000000000; - result->tv_nsec = nanoseconds%(long long)1000000000; -} - void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b) { long microseconds=0; microseconds = ((long)a->tv_sec - (long)b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec); diff --git a/daemon/call.h b/daemon/call.h index 1c43d86b7..8be512487 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -190,8 +190,6 @@ struct stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; - struct timespec start; - struct timespec end; }; struct totalstats { diff --git a/daemon/cli.c b/daemon/cli.c index 0591ec581..e6e4300ab 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include "poller.h" #include "aux.h" @@ -148,10 +146,9 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m if (PS_ISSET(ps, FALLBACK_RTCP)) continue; - struct timespec result; - timespec_subtract(&result,&(ps->stats.end),&(ps->stats.start)); + printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " - "%llu p, %llu b, %llu e, %llu last_packet, %llu.%9llu delay\n", + "%llu p, %llu b, %llu e, %llu last_packet\n", md->index, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, @@ -159,9 +156,7 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m (unsigned long long) ps->stats.packets, (unsigned long long) ps->stats.bytes, (unsigned long long) ps->stats.errors, - (unsigned long long) ps->last_packet, - (unsigned long long) result.tv_sec, - (unsigned long long) result.tv_nsec); + (unsigned long long) ps->last_packet); ADJUSTLEN(printlen,outbufend,replybuffer); } } diff --git a/daemon/graphite.c b/daemon/graphite.c index 55b32501d..f886584af 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -144,4 +144,3 @@ void graphite_loop_run(struct callmaster* callmaster, int seconds) { sleep: usleep(100000); } - diff --git a/daemon/kernel.c b/daemon/kernel.c index 552522c12..670f5496e 100644 --- a/daemon/kernel.c +++ b/daemon/kernel.c @@ -102,20 +102,6 @@ int kernel_del_stream(int fd, u_int16_t p) { return -1; } -int kernel_measure_delay(int fd) { - struct rtpengine_message msg; - int ret; - - ZERO(msg); - msg.cmd = MMG_MEASUREDELAY; - - ret = write(fd, &msg, sizeof(msg)); - if (ret > 0) - return 0; - - ilog(LOG_ERROR, "Failed to delete relay stream from kernel: %s", strerror(errno)); - return -1; -} GList *kernel_list(unsigned int id) { char str[64]; @@ -133,7 +119,6 @@ GList *kernel_list(unsigned int id) { for (;;) { buf = g_slice_alloc(sizeof(*buf)); ret = read(fd, buf, sizeof(*buf)); - if (ret != sizeof(*buf)) break; li = g_list_prepend(li, buf); diff --git a/daemon/main.c b/daemon/main.c index 333a71d46..50da00044 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -27,7 +27,6 @@ #include "call_interfaces.h" #include "cli.h" #include "graphite.h" -#include "measuredelay.h" @@ -630,13 +629,6 @@ static void timer_loop(void *d) { poller_timers_wait_run(p, 100); } -static void measuredelay_loop(void *d) { - struct callmaster *cm = d; - - while (!global_shutdown) - measuredelay_loop_run(cm,1); // time in seconds -} - static void graphite_loop(void *d) { struct callmaster *cm = d; @@ -670,7 +662,6 @@ int main(int argc, char **argv) { thread_create_detach(sighandler, NULL); thread_create_detach(timer_loop, ctx.p); - thread_create_detach(measuredelay_loop, ctx.m); if (graphite_ip) thread_create_detach(graphite_loop, ctx.m); diff --git a/daemon/measuredelay.c b/daemon/measuredelay.c deleted file mode 100644 index 846d51817..000000000 --- a/daemon/measuredelay.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * meauredelay.c - * - * Created on: Feb 13, 2015 - * Author: fmetz - */ - -#include "log.h" -#include "call.h" -#include "measuredelay.h" -#include "kernel.h" - -static struct callmaster* cm=0; -static time_t g_now, next_run; - -void measuredelay_loop_run(struct callmaster* callmaster, int seconds) { - - int rc=0; - - g_now = time(NULL); - if (g_now < next_run) - goto sleep; - - next_run = g_now + seconds; - - if (!cm) - cm = callmaster; - - kernel_measure_delay(cm->conf.kernelfd); - -sleep: - usleep(100000); -} diff --git a/daemon/measuredelay.h b/daemon/measuredelay.h deleted file mode 100644 index 96f5d7798..000000000 --- a/daemon/measuredelay.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * measuredelay.h - * - * Created on: Feb 13, 2015 - * Author: fmetz - */ - -#ifndef MEASUREDELAY_H_ -#define MEASUREDELAY_H_ - -void measuredelay_loop_run(struct callmaster* callmaster, int seconds); - - -#endif /* MEASUREDELAY_H_ */ diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 7a134f05e..8589a02ca 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -1624,9 +1624,6 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz struct rtpengine_table *t; struct rtpengine_message msg; int err; - int port; - struct rtpengine_target *g; - unsigned long flags; if (buflen != sizeof(msg)) return -EIO; @@ -1664,19 +1661,6 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz goto err; break; - case MMG_MEASUREDELAY: - port=0; - if (t==NULL) - break; - g = find_next_target(t, &port); - while (g != NULL) { - spin_lock_irqsave(&g->stats_lock, flags); - g->stats.measureactive=1; - spin_unlock_irqrestore(&g->stats_lock, flags); - g = find_next_target(t, &port); - } - break; - default: printk(KERN_WARNING "xt_RTPENGINE unimplemented op %u\n", msg.cmd); err = -EINVAL; @@ -1808,8 +1792,6 @@ drop: static int send_proxy_packet(struct sk_buff *skb, struct re_address *src, struct re_address *dst, unsigned char tos) { - printk(KERN_WARNING "xt_RTPENGINE send_proxy_packet\n"); - if (src->family != dst->family) goto drop; @@ -2123,7 +2105,7 @@ static inline int is_dtls(struct sk_buff *skb) { return 1; } -static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src, struct timespec *starttime) { +static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src) { struct udphdr *uh; struct rtpengine_target *g; struct sk_buff *skb2; @@ -2230,15 +2212,8 @@ not_rtp: err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos); - out: spin_lock_irqsave(&g->stats_lock, flags); - if (g->stats.measureactive==1) { - g->stats.start = *starttime; - getnstimeofday(&g->stats.end); - g->stats.measureactive=0; - } - printk(KERN_WARNING "xt_RTPENGINE failed to create /proc entry for ID %llu\n", g->stats.start.tv_nsec); if (err) g->stats.errors++; else { @@ -2279,8 +2254,6 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para struct iphdr *ih; struct rtpengine_table *t; struct re_address src; - struct timespec starttime; - getnstimeofday(&starttime); t = get_table(pinfo->id); if (!t) @@ -2299,7 +2272,8 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET; src.u.ipv4 = ih->saddr; - return rtpengine46(skb, t, &src, &starttime); + + return rtpengine46(skb, t, &src); skip2: kfree_skb(skb); @@ -2322,8 +2296,6 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para struct ipv6hdr *ih; struct rtpengine_table *t; struct re_address src; - struct timespec starttime; - getnstimeofday(&starttime); t = get_table(pinfo->id); if (!t) @@ -2342,7 +2314,8 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET6; memcpy(&src.u.ipv6, &ih->saddr, sizeof(src.u.ipv6)); - return rtpengine46(skb, t, &src, &starttime); + + return rtpengine46(skb, t, &src); skip2: kfree_skb(skb); diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index cde73dff2..5f419a08c 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -9,9 +9,6 @@ struct rtpengine_stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; - struct timespec start; - struct timespec end; - u_int32_t measureactive; }; struct re_address { @@ -89,7 +86,6 @@ struct rtpengine_message { MMG_ADD, MMG_DEL, MMG_UPDATE, - MMG_MEASUREDELAY, } cmd; struct rtpengine_target_info target; From 6d33ef76b0bcdf7c0e9317fd090fdc83c27dfe5d Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Wed, 18 Mar 2015 16:15:31 +0100 Subject: [PATCH 4/4] Implemented delay measurement of RTP packets in kernel. --- daemon/Makefile | 2 +- daemon/call.c | 95 ++++++++++++++++++++-------- daemon/call.h | 5 +- daemon/cli.c | 40 ++++++++++-- daemon/kernel.c | 15 ----- daemon/main.c | 10 +-- daemon/measuredelay.c | 33 ---------- daemon/measuredelay.h | 14 ----- kernel-module/rtpengine_config.h | 15 +++++ kernel-module/xt_RTPENGINE.c | 105 +++++++++++++++++++++++++------ kernel-module/xt_RTPENGINE.h | 9 ++- 11 files changed, 212 insertions(+), 131 deletions(-) delete mode 100644 daemon/measuredelay.c delete mode 100644 daemon/measuredelay.h create mode 100644 kernel-module/rtpengine_config.h diff --git a/daemon/Makefile b/daemon/Makefile index b1c762f73..24d0637b6 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -63,7 +63,7 @@ endif SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_udp.c redis.c \ bencode.c cookie_cache.c udp_listener.c control_ng.c sdp.c str.c stun.c rtcp.c \ - crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c measuredelay.c + crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/call.c b/daemon/call.c index 26a85bfab..6b08a0dfb 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -32,7 +32,7 @@ #include "rtcp.h" #include "rtp.h" #include "call_interfaces.h" - +#include "rtpengine_config.h" @@ -1344,10 +1344,13 @@ static void callmaster_timer(void *ptr) { DS(bytes); DS(errors); +#if (RE_HAS_MEASUREDELAY) mutex_lock(&m->statspslock); - ps->stats.start = m->statsps.start = ke->stats.start; - ps->stats.end = m->statsps.end = ke->stats.end; + ps->stats.delay_min = m->statsps.delay_min = ke->stats.delay_min; + ps->stats.delay_avg = m->statsps.delay_avg = ke->stats.delay_avg; + ps->stats.delay_max = m->statsps.delay_max = ke->stats.delay_max; mutex_unlock(&m->statspslock); +#endif mutex_lock(&ps->in_lock); @@ -1358,8 +1361,11 @@ static void callmaster_timer(void *ptr) { ps->kernel_stats.bytes = ke->stats.bytes; ps->kernel_stats.errors = ke->stats.errors; - ps->kernel_stats.start = ke->stats.start; - ps->kernel_stats.end = ke->stats.end; +#if (RE_HAS_MEASUREDELAY) + ps->kernel_stats.delay_min = ke->stats.delay_min; + ps->kernel_stats.delay_avg = ke->stats.delay_avg; + ps->kernel_stats.delay_max = ke->stats.delay_max; +#endif update = 0; @@ -2383,13 +2389,6 @@ static void unkernelize(struct packet_stream *p) { PS_CLEAR(p, KERNELIZED); } -void timespec_subtract (struct timespec *result, const struct timespec *a, const struct timespec *b) { - long long nanoseconds=0; - nanoseconds = ((long)a->tv_sec - (long long)b->tv_sec) * 1000000000 + ((long long)a->tv_nsec - (long long)b->tv_nsec); - result->tv_sec = nanoseconds/(long long)1000000000; - result->tv_nsec = nanoseconds%(long long)1000000000; -} - void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b) { long microseconds=0; microseconds = ((long)a->tv_sec - (long)b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec); @@ -2502,21 +2501,63 @@ void call_destroy(struct call *c) { if (_log_facility_cdr) { const char* protocol = (!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? "rtcp" : "rtp"; - cdrbufcur += sprintf(cdrbufcur, - "ml%i_midx%u_%s_endpoint_ip=%s, " - "ml%i_midx%u_%s_endpoint_port=%u, " - "ml%i_midx%u_%s_local_relay_port=%u, " - "ml%i_midx%u_%s_relayed_packets=%llu, " - "ml%i_midx%u_%s_relayed_bytes=%llu, " - "ml%i_midx%u_%s_relayed_errors=%llu, " - "ml%i_midx%u_%s_last_packet=%llu, ", - cdrlinecnt, md->index, protocol, addr, - cdrlinecnt, md->index, protocol, ps->endpoint.port, - cdrlinecnt, md->index, protocol, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), - cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.packets, - cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.bytes, - cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.errors, - cdrlinecnt, md->index, protocol, (unsigned long long) ps->last_packet); + if(!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) { + cdrbufcur += sprintf(cdrbufcur, + "ml%i_midx%u_%s_endpoint_ip=%s, " + "ml%i_midx%u_%s_endpoint_port=%u, " + "ml%i_midx%u_%s_local_relay_port=%u, " + "ml%i_midx%u_%s_relayed_packets=%llu, " + "ml%i_midx%u_%s_relayed_bytes=%llu, " + "ml%i_midx%u_%s_relayed_errors=%llu, " + "ml%i_midx%u_%s_last_packet=%llu, ", + cdrlinecnt, md->index, protocol, addr, + cdrlinecnt, md->index, protocol, ps->endpoint.port, + cdrlinecnt, md->index, protocol, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.packets, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.bytes, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.errors, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->last_packet); + } else { +#if (RE_HAS_MEASUREDELAY) + cdrbufcur += sprintf(cdrbufcur, + "ml%i_midx%u_%s_endpoint_ip=%s, " + "ml%i_midx%u_%s_endpoint_port=%u, " + "ml%i_midx%u_%s_local_relay_port=%u, " + "ml%i_midx%u_%s_relayed_packets=%llu, " + "ml%i_midx%u_%s_relayed_bytes=%llu, " + "ml%i_midx%u_%s_relayed_errors=%llu, " + "ml%i_midx%u_%s_last_packet=%llu, " + "ml%i_midx%u_%s_delay_min=%llu.%09llu, " + "ml%i_midx%u_%s_delay_avg=%llu.%09llu, " + "ml%i_midx%u_%s_delay_max=%llu.%09llu, ", + cdrlinecnt, md->index, protocol, addr, + cdrlinecnt, md->index, protocol, ps->endpoint.port, + cdrlinecnt, md->index, protocol, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.packets, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.bytes, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.errors, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->last_packet, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.delay_min.tv_sec, (unsigned long long) ps->stats.delay_min.tv_nsec, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.delay_avg.tv_sec, (unsigned long long) ps->stats.delay_avg.tv_nsec, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.delay_max.tv_sec, (unsigned long long) ps->stats.delay_max.tv_nsec); +#else + cdrbufcur += sprintf(cdrbufcur, + "ml%i_midx%u_%s_endpoint_ip=%s, " + "ml%i_midx%u_%s_endpoint_port=%u, " + "ml%i_midx%u_%s_local_relay_port=%u, " + "ml%i_midx%u_%s_relayed_packets=%llu, " + "ml%i_midx%u_%s_relayed_bytes=%llu, " + "ml%i_midx%u_%s_relayed_errors=%llu, " + "ml%i_midx%u_%s_last_packet=%llu, ", + cdrlinecnt, md->index, protocol, addr, + cdrlinecnt, md->index, protocol, ps->endpoint.port, + cdrlinecnt, md->index, protocol, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.packets, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.bytes, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->stats.errors, + cdrlinecnt, md->index, protocol, (unsigned long long) ps->last_packet); +#endif + } } ilog(LOG_INFO, "------ Media #%u, port %5u <> %15s:%-5hu%s, " diff --git a/daemon/call.h b/daemon/call.h index 1c43d86b7..8960de9df 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -190,8 +190,9 @@ struct stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; - struct timespec start; - struct timespec end; + struct timespec delay_min; + struct timespec delay_avg; + struct timespec delay_max; }; struct totalstats { diff --git a/daemon/cli.c b/daemon/cli.c index 4d105c215..8d610c9ba 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -16,6 +16,7 @@ #include "call.h" #include "cli.h" +#include "rtpengine_config.h" static const char* TRUNCATED = " ... Output truncated. Increase Output Buffer ...\n"; @@ -148,10 +149,22 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m if (PS_ISSET(ps, FALLBACK_RTCP)) continue; - struct timespec result; - timespec_subtract(&result,&(ps->stats.end),&(ps->stats.start)); + +#if (RE_HAS_MEASUREDELAY) + if (!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) { + printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " + "%llu p, %llu b, %llu e, %llu last_packet\n", + md->index, + (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), + smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, + (!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? " (RTCP)" : "", + (unsigned long long) ps->stats.packets, + (unsigned long long) ps->stats.bytes, + (unsigned long long) ps->stats.errors, + (unsigned long long) ps->last_packet); + } else { printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " - "%llu p, %llu b, %llu e, %llu last_packet, %llu.%09llu delay\n", + "%llu p, %llu b, %llu e, %llu last_packet, %llu.%09llu delay_min, %llu.%09llu delay_avg, %llu.%09llu delay_max\n", md->index, (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, @@ -160,8 +173,25 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m (unsigned long long) ps->stats.bytes, (unsigned long long) ps->stats.errors, (unsigned long long) ps->last_packet, - (unsigned long long) result.tv_sec, - (unsigned long long) result.tv_nsec); + (unsigned long long) ps->stats.delay_min.tv_sec, + (unsigned long long) ps->stats.delay_min.tv_nsec, + (unsigned long long) ps->stats.delay_avg.tv_sec, + (unsigned long long) ps->stats.delay_avg.tv_nsec, + (unsigned long long) ps->stats.delay_max.tv_sec, + (unsigned long long) ps->stats.delay_max.tv_nsec); + } +#else + printlen = snprintf(replybuffer,(outbufend-replybuffer), "------ Media #%u, port %5u <> %15s:%-5hu%s, " + "%llu p, %llu b, %llu e, %llu last_packet\n", + md->index, + (unsigned int) (ps->sfd ? ps->sfd->fd.localport : 0), + smart_ntop_p_buf(&ps->endpoint.ip46), ps->endpoint.port, + (!PS_ISSET(ps, RTP) && PS_ISSET(ps, RTCP)) ? " (RTCP)" : "", + (unsigned long long) ps->stats.packets, + (unsigned long long) ps->stats.bytes, + (unsigned long long) ps->stats.errors, + (unsigned long long) ps->last_packet); +#endif ADJUSTLEN(printlen,outbufend,replybuffer); } } diff --git a/daemon/kernel.c b/daemon/kernel.c index 552522c12..437ed5c02 100644 --- a/daemon/kernel.c +++ b/daemon/kernel.c @@ -102,21 +102,6 @@ int kernel_del_stream(int fd, u_int16_t p) { return -1; } -int kernel_measure_delay(int fd) { - struct rtpengine_message msg; - int ret; - - ZERO(msg); - msg.cmd = MMG_MEASUREDELAY; - - ret = write(fd, &msg, sizeof(msg)); - if (ret > 0) - return 0; - - ilog(LOG_ERROR, "Failed to delete relay stream from kernel: %s", strerror(errno)); - return -1; -} - GList *kernel_list(unsigned int id) { char str[64]; int fd; diff --git a/daemon/main.c b/daemon/main.c index 333a71d46..9d9d94d92 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -27,7 +27,6 @@ #include "call_interfaces.h" #include "cli.h" #include "graphite.h" -#include "measuredelay.h" @@ -630,13 +629,6 @@ static void timer_loop(void *d) { poller_timers_wait_run(p, 100); } -static void measuredelay_loop(void *d) { - struct callmaster *cm = d; - - while (!global_shutdown) - measuredelay_loop_run(cm,1); // time in seconds -} - static void graphite_loop(void *d) { struct callmaster *cm = d; @@ -670,7 +662,7 @@ int main(int argc, char **argv) { thread_create_detach(sighandler, NULL); thread_create_detach(timer_loop, ctx.p); - thread_create_detach(measuredelay_loop, ctx.m); + if (graphite_ip) thread_create_detach(graphite_loop, ctx.m); diff --git a/daemon/measuredelay.c b/daemon/measuredelay.c deleted file mode 100644 index 846d51817..000000000 --- a/daemon/measuredelay.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * meauredelay.c - * - * Created on: Feb 13, 2015 - * Author: fmetz - */ - -#include "log.h" -#include "call.h" -#include "measuredelay.h" -#include "kernel.h" - -static struct callmaster* cm=0; -static time_t g_now, next_run; - -void measuredelay_loop_run(struct callmaster* callmaster, int seconds) { - - int rc=0; - - g_now = time(NULL); - if (g_now < next_run) - goto sleep; - - next_run = g_now + seconds; - - if (!cm) - cm = callmaster; - - kernel_measure_delay(cm->conf.kernelfd); - -sleep: - usleep(100000); -} diff --git a/daemon/measuredelay.h b/daemon/measuredelay.h deleted file mode 100644 index 96f5d7798..000000000 --- a/daemon/measuredelay.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * measuredelay.h - * - * Created on: Feb 13, 2015 - * Author: fmetz - */ - -#ifndef MEASUREDELAY_H_ -#define MEASUREDELAY_H_ - -void measuredelay_loop_run(struct callmaster* callmaster, int seconds); - - -#endif /* MEASUREDELAY_H_ */ diff --git a/kernel-module/rtpengine_config.h b/kernel-module/rtpengine_config.h new file mode 100644 index 000000000..13188e85c --- /dev/null +++ b/kernel-module/rtpengine_config.h @@ -0,0 +1,15 @@ +/* + * rtpengine_config.h + * + * Description: Config file with preprocessor config makros + * + * Created on: Mar 18, 2015 + * Author: fmetz + */ + +#ifndef RTPENGINE_CONFIG_H_ +#define RTPENGINE_CONFIG_H_ + +#define RE_HAS_MEASUREDELAY 1 + +#endif /* RTPENGINE_CONFIG_H_ */ diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 506bdf3b1..8def1478e 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -27,6 +27,8 @@ #include "xt_RTPENGINE.h" #endif +#include "rtpengine_config.h" + MODULE_LICENSE("GPL"); @@ -1664,19 +1666,6 @@ static ssize_t proc_control_write(struct file *file, const char __user *buf, siz goto err; break; - case MMG_MEASUREDELAY: - port=0; - if (t==NULL) - break; - g = find_next_target(t, &port); - while (g != NULL) { - spin_lock_irqsave(&g->stats_lock, flags); - g->stats.measureactive=1; - spin_unlock_irqrestore(&g->stats_lock, flags); - g = find_next_target(t, &port); - } - break; - default: printk(KERN_WARNING "xt_RTPENGINE unimplemented op %u\n", msg.cmd); err = -EINVAL; @@ -2122,7 +2111,48 @@ static inline int is_dtls(struct sk_buff *skb) { return 1; } -static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src, struct timespec *starttime) { +static void re_timespec_subtract (struct timespec *result, const struct timespec *a, const struct timespec *b) { + long long nanoseconds=0; + nanoseconds = ((long)a->tv_sec - (long long)b->tv_sec) * (long long)1000000000 + ((long long)a->tv_nsec - (long long)b->tv_nsec); + result->tv_sec = nanoseconds/(long long)1000000000; + result->tv_nsec = nanoseconds%(long long)1000000000; +} + +static void re_timespec_multiply(struct timespec *result, const struct timespec *a, const long long multiplier) { + long long nanoseconds=0; + nanoseconds = ((long)a->tv_sec * (long long)1000000000) + (long long)a->tv_nsec * multiplier; + result->tv_sec = nanoseconds/(long long)1000000000; + result->tv_nsec = nanoseconds%(long long)1000000000; +} + +static void re_timespec_devide(struct timespec *result, const struct timespec *a, const long devisor) { + long long nanoseconds=0; + nanoseconds = ((long)a->tv_sec * (long long)1000000000) + (long long)a->tv_nsec / devisor; + result->tv_sec = nanoseconds/(long long)1000000000; + result->tv_nsec = nanoseconds%(long long)1000000000; +} + +static void re_timespec_add(struct timespec *result, const struct timespec *a, const struct timespec *b) { + long long nanoseconds=0; + nanoseconds = ((long)a->tv_sec + (long long)b->tv_sec) * (long long)1000000000 + ((long long)a->tv_nsec + (long long)b->tv_nsec); + result->tv_sec = nanoseconds/(long long)1000000000; + result->tv_nsec = nanoseconds%(long long)1000000000; +} + +/* Return negative, zero, positive if A < B, A == B, A > B, respectively. + Assume the nanosecond components are in range, or close to it. */ +static int re_timespec_cmp (struct timespec *a, struct timespec *b) +{ + return (a->tv_sec < b->tv_sec ? -1 + : a->tv_sec > b->tv_sec ? 1 + : a->tv_nsec - b->tv_nsec); +} + +#if (RE_HAS_MEASUREDELAY) + static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src, struct timespec *starttime) { +#else + static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct re_address *src) { +#endif struct udphdr *uh; struct rtpengine_target *g; struct sk_buff *skb2; @@ -2133,6 +2163,10 @@ static unsigned int rtpengine46(struct sk_buff *skb, struct rtpengine_table *t, struct rtp_parsed rtp; u_int64_t pkt_idx = 0; +#if (RE_HAS_MEASUREDELAY) + struct timespec endtime, delay; +#endif + skb_reset_transport_header(skb); uh = udp_hdr(skb); skb_pull(skb, sizeof(*uh)); @@ -2232,17 +2266,35 @@ not_rtp: out: spin_lock_irqsave(&g->stats_lock, flags); - if (g->stats.measureactive==1) { - g->stats.start = *starttime; - getnstimeofday(&g->stats.end); - g->stats.measureactive=0; - } if (err) g->stats.errors++; else { g->stats.packets++; g->stats.bytes += skb->len; + +#if (RE_HAS_MEASUREDELAY) + getnstimeofday(&endtime); + + re_timespec_subtract(&delay,&endtime, starttime); + + if (g->stats.packets==1) { + g->stats.delay_min=delay; + g->stats.delay_avg=delay; + g->stats.delay_max=delay; + } else { + if (re_timespec_cmp(&g->stats.delay_min,&delay)>0) { + g->stats.delay_min = delay; + } + if (re_timespec_cmp(&g->stats.delay_max,&delay)<0) { + g->stats.delay_max = delay; + } + + re_timespec_multiply(&g->stats.delay_avg,&g->stats.delay_avg,g->stats.packets-1); + re_timespec_add(&g->stats.delay_avg,&g->stats.delay_avg,&delay); + re_timespec_devide(&g->stats.delay_avg,&g->stats.delay_avg,g->stats.packets); + } +#endif } spin_unlock_irqrestore(&g->stats_lock, flags); @@ -2278,8 +2330,11 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para struct iphdr *ih; struct rtpengine_table *t; struct re_address src; + +#if (RE_HAS_MEASUREDELAY) struct timespec starttime; getnstimeofday(&starttime); +#endif t = get_table(pinfo->id); if (!t) @@ -2298,8 +2353,11 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET; src.u.ipv4 = ih->saddr; +#if (RE_HAS_MEASUREDELAY) return rtpengine46(skb, t, &src, &starttime); - +#else + return rtpengine46(skb, t, &src); +#endif skip2: kfree_skb(skb); skip3: @@ -2321,8 +2379,11 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para struct ipv6hdr *ih; struct rtpengine_table *t; struct re_address src; + +#if (RE_HAS_MEASUREDELAY) struct timespec starttime; getnstimeofday(&starttime); +#endif t = get_table(pinfo->id); if (!t) @@ -2341,7 +2402,11 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para memset(&src, 0, sizeof(src)); src.family = AF_INET6; memcpy(&src.u.ipv6, &ih->saddr, sizeof(src.u.ipv6)); +#if (RE_HAS_MEASUREDELAY) return rtpengine46(skb, t, &src, &starttime); +#else + return rtpengine46(skb, t, &src); +#endif skip2: kfree_skb(skb); diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index cde73dff2..6ba4fed32 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -9,9 +9,9 @@ struct rtpengine_stats { u_int64_t packets; u_int64_t bytes; u_int64_t errors; - struct timespec start; - struct timespec end; - u_int32_t measureactive; + struct timespec delay_min; + struct timespec delay_avg; + struct timespec delay_max; }; struct re_address { @@ -88,8 +88,7 @@ struct rtpengine_message { MMG_NOOP = 1, MMG_ADD, MMG_DEL, - MMG_UPDATE, - MMG_MEASUREDELAY, + MMG_UPDATE } cmd; struct rtpengine_target_info target;