From ec5a543f0f9803c94433bf79cfe1ad6a54eb5b78 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Wed, 18 Feb 2015 07:36:25 +0100 Subject: [PATCH 01/13] Added prefix config parameter to graphite acc. to OPS --- README.md | 5 +++++ daemon/graphite.c | 17 +++++++++++++++++ daemon/graphite.h | 1 + daemon/main.c | 19 ++++++++++++------- debian/ngcp-rtpengine-daemon.default | 3 ++- debian/ngcp-rtpengine-daemon.init | 1 + el/rtpengine.init | 5 +++++ 7 files changed, 43 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9727cef63..b878745d7 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ option and which are reproduced below: --dtls-passive Always prefer DTLS passive role -g, --graphite=[IP46:]PORT TCP address of graphite statistics server -w, --graphite-interval=INT Graphite data statistics send interval + --graphite-prefix=STRING Graphite prefix for every line Most of these options are indeed optional, with two exceptions. It's mandatory to specify at least one local IP address through `--interface`, and at least one of the `--listen-...` options must be given. @@ -364,6 +365,10 @@ The options are described in more detail below. Interval of the time when information is sent to the graphite server. +* --graphite-prefix + + Add a prefix for every graphite line. + A typical command line (enabling both UDP and NG protocols) thus may look like: /usr/sbin/rtpengine --table=0 --interface=10.64.73.31 --interface=2001:db8::4f3:3d \ diff --git a/daemon/graphite.c b/daemon/graphite.c index f886584af..8a3ebd088 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -12,6 +12,7 @@ #include "log.h" #include "call.h" +#include "graphite.h" static int graphite_sock=-1; static u_int32_t graphite_ipaddress; @@ -19,6 +20,11 @@ static int graphite_port=0; static struct callmaster* cm=0; //struct totalstats totalstats_prev; static time_t g_now, next_run; +static char* graphite_prefix = NULL; + +void set_prefix(char* prefix) { + graphite_prefix = prefix; +} int connect_to_graphite_server(u_int32_t ipaddress, int port) { @@ -89,16 +95,27 @@ int send_graphite_data() { mutex_lock(&cm->totalstats_lock); + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.average_call_dur.tv_sec %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_sec,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.average_call_dur.tv_usec %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_usec,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.forced_term_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_forced_term_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.managed_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_managed_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.nopacket_relayed_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_nopacket_relayed_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.oneway_stream_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_oneway_stream_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.regular_term_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_regular_term_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.relayed_errors %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_relayed_errors,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.relayed_packets %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_relayed_packets,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.silent_timeout_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_silent_timeout_sess,(unsigned long long)g_now); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.timeout_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_timeout_sess,(unsigned long long)g_now); ptr += rc; ZERO(cm->totalstats_interval); diff --git a/daemon/graphite.h b/daemon/graphite.h index 0b51e7b9a..a1a89267f 100644 --- a/daemon/graphite.h +++ b/daemon/graphite.h @@ -13,5 +13,6 @@ int connect_to_graphite_server(u_int32_t ipaddress, int port); int send_graphite_data(); void graphite_loop_run(struct callmaster* cm, int seconds); +void set_prefix(char* prefix); #endif /* GRAPHITE_H_ */ diff --git a/daemon/main.c b/daemon/main.c index 50da00044..4f0c29aa7 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -257,9 +257,10 @@ static void options(int *argc, char ***argv) { char *listenngs = NULL; char *listencli = NULL; char *graphitep = NULL; + char *graphite_prefix_s = NULL; char *redisps = NULL; char *log_facility_s = NULL; - char *log_facility_cdr_s = NULL; + char *log_facility_cdr_s = NULL; int version = 0; int sip_source = 0; @@ -274,6 +275,7 @@ static void options(int *argc, char ***argv) { { "listen-cli", 'c', 0, G_OPTION_ARG_STRING, &listencli, "UDP port to listen on, CLI", "[IP46:]PORT" }, { "graphite", 'g', 0, G_OPTION_ARG_STRING, &graphitep, "Address of the graphite server", "[IP46:]PORT" }, { "graphite-interval", 'w', 0, G_OPTION_ARG_INT, &graphite_interval, "Graphite send interval in seconds", "INT" }, + { "graphite-prefix",0, 0, G_OPTION_ARG_STRING, &graphite_prefix_s, "Prefix for graphite line", "STRING"}, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "Default TOS value to set on streams", "INT" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" }, @@ -340,6 +342,9 @@ static void options(int *argc, char ***argv) { die("Invalid IP or port (--graphite)"); } + if (graphite_prefix_s) + set_prefix(graphite_prefix_s); + if (tos < 0 || tos > 255) die("Invalid TOS value"); @@ -369,12 +374,12 @@ static void options(int *argc, char ***argv) { } } - if (log_facility_cdr_s) { - if (!parse_log_facility(log_facility_cdr_s, &_log_facility_cdr)) { - print_available_log_facilities(); - die ("Invalid log facility for CDR '%s' (--log-facility-cdr)\n", log_facility_cdr_s); - } - } + if (log_facility_cdr_s) { + if (!parse_log_facility(log_facility_cdr_s, &_log_facility_cdr)) { + print_available_log_facilities(); + die ("Invalid log facility for CDR '%s' (--log-facility-cdr)\n", log_facility_cdr_s); + } + } if (_log_stderr) { write_log = log_to_stderr; diff --git a/debian/ngcp-rtpengine-daemon.default b/debian/ngcp-rtpengine-daemon.default index 20b10c3d5..3f259c0c6 100644 --- a/debian/ngcp-rtpengine-daemon.default +++ b/debian/ngcp-rtpengine-daemon.default @@ -24,4 +24,5 @@ TABLE=0 # NUM_THREADS=5 # DELETE_DELAY=30 # GRAPHITE=9006 -# GRAPHITE_INTERVAL=60 \ No newline at end of file +# GRAPHITE_INTERVAL=60 +# GRAPHITE_PREFIX=myownprefix diff --git a/debian/ngcp-rtpengine-daemon.init b/debian/ngcp-rtpengine-daemon.init index 1c7e96f5c..64ce42902 100755 --- a/debian/ngcp-rtpengine-daemon.init +++ b/debian/ngcp-rtpengine-daemon.init @@ -74,6 +74,7 @@ OPTIONS="$OPTIONS --table=$TABLE" [ -z "$DELETE_DELAY" ] || OPTIONS="$OPTIONS --delete-delay=$DELETE_DELAY" [ -z "$GRAPHITE" ] || OPTIONS="$OPTIONS --graphite=$GRAPHITE" [ -z "$GRAPHITE_INTERVAL" ] || OPTIONS="$OPTIONS --graphite-interval=$GRAPHITE_INTERVAL" +[ -z "$GRAPHITE_PREFIX" ] || OPTIONS="$OPTIONS --graphite-prefix=$GRAPHITE_PREFIX" if test "$FORK" = "no" ; then OPTIONS="$OPTIONS --foreground" fi diff --git a/el/rtpengine.init b/el/rtpengine.init index 1fb33ce62..48b2c215c 100644 --- a/el/rtpengine.init +++ b/el/rtpengine.init @@ -153,6 +153,11 @@ build_opts() { OPTS+=" --graphite-interval=$GRAPHITE_INTERVAL" fi + if [[ -n "$GRAPHITE_PREFIX" ]] + then + OPTS+=" --graphite-prefix=$GRAPHITE_PREFIX" + fi + if [[ -n "$LOG_FACILITY_CDR" ]] then OPTS+=" --log-facility-cdr=$LOG_FACILITY_CDR" From 6bc7a77e9bd386bf1564e87561e1956011e6cfad Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Thu, 19 Feb 2015 08:45:48 +0100 Subject: [PATCH 02/13] 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 d98d17b92f84df550eedadf5406ec2c46d96de18 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Wed, 25 Feb 2015 17:25:43 +0100 Subject: [PATCH 03/13] Implemented non blocking connect to graphite due to firewall issues. As requested, the connect call blocks if a firewall discards the TCP SYN and the rtpengine could not be terminated. This Impl. fixes the behaviour. --- daemon/graphite.c | 110 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/daemon/graphite.c b/daemon/graphite.c index 8a3ebd088..979f08467 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -9,12 +9,18 @@ #include #include #include +#include +#include +#include +#include +#include #include "log.h" #include "call.h" #include "graphite.h" static int graphite_sock=-1; +static int connectinprogress=0; static u_int32_t graphite_ipaddress; static int graphite_port=0; static struct callmaster* cm=0; @@ -26,10 +32,34 @@ void set_prefix(char* prefix) { graphite_prefix = prefix; } +/** + * Set a file descriptor to blocking or non-blocking mode. + * + * @param fd The file descriptor + * @param blocking 0:non-blocking mode, 1:blocking mode + * + * @return 1:success, 0:failure. + **/ +int fd_set_blocking(int fd, int blocking) { + /* Save the current flags */ + int flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) + return 0; + + if (blocking) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + return fcntl(fd, F_SETFL, flags) != -1; +} + int connect_to_graphite_server(u_int32_t ipaddress, int port) { + if (graphite_sock>0) + close(graphite_sock); + graphite_sock=-1; - //int reconnect=0; + int rc=0; struct sockaddr_in sin; memset(&sin,0,sizeof(sin)); @@ -38,9 +68,9 @@ int connect_to_graphite_server(u_int32_t ipaddress, int port) { graphite_ipaddress = ipaddress; graphite_port = port; - rc = graphite_sock = socket(AF_INET, SOCK_STREAM,0); - if(rc<0) { - ilog(LOG_ERROR,"Couldn't make socket for connecting to graphite."); + graphite_sock = socket(AF_INET, SOCK_STREAM,0); + if(graphite_sock<0) { + ilog(LOG_ERROR,"Couldn't make socket for connecting to graphite.Reason:%s\n",strerror(errno)); return -1; } @@ -54,18 +84,26 @@ int connect_to_graphite_server(u_int32_t ipaddress, int port) { goto error; } + rc = fd_set_blocking(graphite_sock,0); + if (!rc) { + ilog(LOG_ERROR,"Could not set the socket to nonblocking."); + goto error; + } + struct in_addr ip; ip.s_addr = graphite_ipaddress; ilog(LOG_INFO, "Connecting to graphite server %s at port:%i with fd:%i",inet_ntoa(ip),graphite_port,graphite_sock); rc = connect(graphite_sock, (struct sockaddr *)&sin, sizeof(sin)); if (rc==-1) { - ilog(LOG_ERROR, "Connection could not be established. Trying again next time of graphite-interval."); + ilog(LOG_WARN, "Connection information:%s\n",strerror(errno)); + if (errno==EINPROGRESS) { + connectinprogress=1; + return 0; + } goto error; } - ilog(LOG_INFO, "Graphite server connected."); - - return graphite_sock; + return 0; error: close(graphite_sock); @@ -137,27 +175,71 @@ error: void graphite_loop_run(struct callmaster* callmaster, int seconds) { int rc=0; + fd_set wfds; + FD_ZERO(&wfds); + struct timeval tv; + int optval=0; + socklen_t optlen=sizeof(optval); + + if (connectinprogress && graphite_sock>0) { + FD_SET(graphite_sock,&wfds); + tv.tv_sec = 0; + tv.tv_usec = 1000000; + + rc = select (graphite_sock+1, NULL, &wfds, NULL, &tv); + if ((rc == -1) && (errno == EINTR)) { + ilog(LOG_ERROR,"Error on the socket."); + close(graphite_sock); + graphite_sock=-1;connectinprogress=0; + return; + } else if (rc==0) { + // timeout + return; + } else { + if (!FD_ISSET(graphite_sock,&wfds)) { + ilog(LOG_WARN,"fd active but not the graphite fd."); + close(graphite_sock); + graphite_sock=-1;connectinprogress=0; + return; + } + rc = getsockopt(graphite_sock, SOL_SOCKET, SO_ERROR, &optval, &optlen); + if (rc) ilog(LOG_ERROR,"getsockopt failure."); + if (optval != 0) { + ilog(LOG_ERROR,"Socket connect failed. fd: %i, Reason: %s\n",graphite_sock, strerror(optval)); + close(graphite_sock); + graphite_sock=-1;connectinprogress=0; + return; + } + ilog(LOG_INFO, "Graphite server connected."); + connectinprogress=0; + next_run=0; // fake next run to skip sleep after reconnect + } + } g_now = time(NULL); - if (g_now < next_run) - goto sleep; + if (g_now < next_run) { + usleep(100000); + return; + } next_run = g_now + seconds; if (!cm) cm = callmaster; - if (graphite_sock < 0) { + if (graphite_sock < 0 && !connectinprogress) { rc = connect_to_graphite_server(graphite_ipaddress, graphite_port); + if (rc) { + close(graphite_sock); + graphite_sock=-1; + } } - if (rc>=0) { + if (graphite_sock>0 && !connectinprogress) { rc = send_graphite_data(); if (rc<0) { ilog(LOG_ERROR,"Sending graphite data failed."); } } -sleep: - usleep(100000); } From 6e7a287f54cac080d552d90266033bdb57266841 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Thu, 26 Feb 2015 18:59:06 +0100 Subject: [PATCH 04/13] Modified average_dur format for graphite. --- daemon/graphite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/daemon/graphite.c b/daemon/graphite.c index 979f08467..f8cb79ab2 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -134,9 +134,7 @@ int send_graphite_data() { mutex_lock(&cm->totalstats_lock); if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } - rc = sprintf(ptr,"%s.totals.average_call_dur.tv_sec %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_sec,(unsigned long long)g_now); ptr += rc; - if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } - rc = sprintf(ptr,"%s.totals.average_call_dur.tv_usec %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_usec,(unsigned long long)g_now); ptr += rc; + rc = sprintf(ptr,"%s.totals.average_call_dur %llu.%06llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_sec,(unsigned long long) cm->totalstats_interval.total_average_call_dur.tv_usec,(unsigned long long)g_now); ptr += rc; if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.forced_term_sess %llu %llu\n",hostname, (unsigned long long) cm->totalstats_interval.total_forced_term_sess,(unsigned long long)g_now); ptr += rc; if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } From e0f9c59274fefac6c54bed42ff748c4a56508af4 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Sun, 15 Mar 2015 13:29:46 +0100 Subject: [PATCH 05/13] 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 06/13] 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 07/13] 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; From cca0f2bf7115af5e8211e49fc83cee10d9296726 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Mon, 30 Mar 2015 11:24:15 +0200 Subject: [PATCH 08/13] Replaced rtpengine-ctl shell script with perl script. --- utils/rtpengine-ctl | 128 +++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/utils/rtpengine-ctl b/utils/rtpengine-ctl index e69deb12c..464fcf0d4 100755 --- a/utils/rtpengine-ctl +++ b/utils/rtpengine-ctl @@ -1,70 +1,76 @@ -#!/bin/bash -# +#!/usr/bin/perl -host=127.0.0.1 -port=9900 -error_rc=255 +use IO::Socket::INET; -prgname=${0##*/} -prgdir=${0%$prgname} +$num_args = $#ARGV + 1; +if ($num_args == 0) { + showusage(); + exit; +} + +# auto-flush on socket +$| = 1; + +my $argumentstring = ""; +my $ip = "127.0.0.1"; +my $port = "9900"; -showusage() { - echo "" - echo " $0 [ -ip -port ] " - echo "" - echo " Supported commands are:" - echo "" - echo " list [ numsessions | sessions | session ]" - echo " numsessions : prints the number of sessions" - echo " sessions : print one-liner session information" - echo " session : print detail about one session" - echo " totals : print total statistics (does not include current sessions)" - echo "" - echo " terminate [ all | ]" - echo " all : terminates all current sessions" - echo " : session is immediately terminated" - echo "" - echo "" - echo " Return Value:" - echo " 0 on success with ouput from server side, other values for failure." - echo "" - exit 0 +for (my $argnum=0; $argnum <= $#ARGV; $argnum++) { + if ($ARGV[$argnum] eq "-ip") { + die "No argument after -ip\n" unless $argnum+1<=$#ARGV; + $argnum = $argnum+1; + $ip = $ARGV[$argnum]; + } elsif ($ARGV[$argnum] eq "-port") { + die "No argument after -port\n" unless $argnum+1<=$#ARGV; + $argnum = $argnum+1; + $port = $ARGV[$argnum]; + } else { + $argumentstring .= "$ARGV[$argnum] "; + } } -if [ $# -eq 0 ]; then showusage; fi +# create a connecting socket +my $socket = new IO::Socket::INET ( + PeerHost => $ip, + PeerPort => $port, + Proto => 'tcp', +); +die "Cannot connect to the rtpengine $!\n" unless $socket; + +$argumentstring = trim($argumentstring); +my $size = $socket->send($argumentstring); + +# notify server that request has been sent +shutdown($socket, 1); + +# receive a response of up to 10MB +my $response = ""; +$socket->recv($response, 1024*1024*10); +print $response; -command -v nc 2>&1 >/dev/null -if [ $? -ne 0 ]; then - echo "Error: $0 requires netcat to be installed." - exit 0 -fi +$socket->close(); -while [ $# -gt 0 ]; do - case $1 in - "-?"|"-help"|"-h") - showusage - ;; - "-ip") - shift - if [ $# -gt 0 ]; then - host=$1 - else - echo "Missing parameter for option '-ip'" >&2 - fi - ;; - "-port") - shift - if [ $# -gt 0 ]; then - port=$1 - else - echo "Missing parameter for option '-port'" >&2 - fi - ;; - *) - varargs="$varargs $1" - esac - shift -done +sub showusage { + print "\n"; + print " rtpengine-ctl [ -ip -port ] \n"; + print "\n"; + print " Supported commands are:\n"; + print "\n"; + print " list [ numsessions | sessions | session | totals ]\n"; + print " numsessions : prints the number of sessions\n"; + print " sessions : print one-liner session information\n"; + print " session : print detail about one session\n"; + print " totals : print total statistics\n"; + print "\n"; + print " terminate [ all | ]\n"; + print " all : terminates all current sessions\n"; + print " : session is immediately terminated\n"; + print "\n"; + print "\n"; + print " Return Value:\n"; + print " 0 on success with ouput from server side, other values for failure.\n"; + print "\n"; +} -echo -n ${varargs} | nc ${host} ${port} +sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s }; From 070212ec3a7a7580eeb182a41d1911dfead0ce90 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Tue, 7 Apr 2015 10:44:10 +0200 Subject: [PATCH 09/13] Added RTCP parsing and option to log that information --- README.md | 6 + daemon/Makefile | 2 +- daemon/call.c | 3 + daemon/log.c | 9 ++ daemon/log.h | 2 + daemon/main.c | 23 ++- daemon/rtcp.c | 75 ++++++++- daemon/rtcp.h | 80 +++++++++- daemon/rtcp_xr.c | 160 +++++++++++++++++++ daemon/rtcp_xr.h | 229 +++++++++++++++++++++++++++ debian/ngcp-rtpengine-daemon.default | 1 + debian/ngcp-rtpengine-daemon.init | 1 + el/rtpengine.init | 5 + 13 files changed, 584 insertions(+), 12 deletions(-) create mode 100644 daemon/rtcp_xr.c create mode 100644 daemon/rtcp_xr.h diff --git a/README.md b/README.md index 9727cef63..a04a182c4 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ option and which are reproduced below: -L, --log-level=INT Mask log priorities above this level --log-facility=daemon|local0|... Syslog facility to use for logging --log-facility-cdr=local0|... Syslog facility to use for logging CDRs + --log-facility-rtcp=local0|... Syslog facility to use for logging RTCP data (take care of traffic amount) -E, --log-stderr Log on stderr instead of syslog -x, --xmlrpc-format=INT XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only --num-threads=INT Number of worker threads to create @@ -322,6 +323,11 @@ The options are described in more detail below. Same as --log-facility with the difference that only CDRs are written to this log facility. +* --log-facilty-rtcp=daemon|local0|...|local7|... + + Same as --log-facility with the difference that only RTCP data is written to this log facility. + Be careful with this parameter since there may be a lot of information written to it. + * -E, --log-stderr Log to stderr instead of syslog. Only useful in combination with `--foreground`. diff --git a/daemon/Makefile b/daemon/Makefile index 24d0637b6..c61c7ea90 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 rtcp_xr.c OBJS= $(SRCS:.c=.o) diff --git a/daemon/call.c b/daemon/call.c index 6b08a0dfb..96321c945 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -672,6 +672,9 @@ loop_ok: if (!sink && PS_ISSET(stream, RTCP)) { sink = stream->rtcp_sink; rtcp = 1; + if (_log_facility_rtcp) { + parse_and_log_rtcp_report(sfd, s->s, s->len); + } } else if (stream->rtcp_sink) { muxed_rtcp = rtcp_demux(s, media); diff --git a/daemon/log.c b/daemon/log.c index 3eec0c1eb..1f5d716da 100644 --- a/daemon/log.c +++ b/daemon/log.c @@ -58,6 +58,7 @@ static const char* const prio_str[] = { gboolean _log_stderr = 0; int _log_facility = LOG_DAEMON; int _log_facility_cdr = 0; +int _log_facility_rtcp = 0; static GHashTable *__log_limiter; @@ -176,6 +177,14 @@ void cdrlog(const char* cdrbuffer) { setlogmask(previous); } +void rtcplog(const char* cdrbuffer) { + int previous; + int mask = LOG_MASK (LOG_INFO); + previous = setlogmask(mask); + syslog(LOG_INFO | _log_facility_rtcp, "%s", cdrbuffer); + setlogmask(previous); +} + void log_init() { mutex_init(&__log_limiter_lock); __log_limiter = g_hash_table_new(g_str_hash, g_str_equal); diff --git a/daemon/log.h b/daemon/log.h index c68a87177..c457f7a7b 100644 --- a/daemon/log.h +++ b/daemon/log.h @@ -23,6 +23,7 @@ struct log_info { extern gboolean _log_stderr; extern int _log_facility; extern int _log_facility_cdr; +extern int _log_facility_rtcp; typedef struct _fac_code { @@ -48,6 +49,7 @@ void log_init(void); void ilog(int prio, const char *fmt, ...)__attribute__ ((format (printf, 2, 3))); void cdrlog(const char* cdrbuffer); +void rtcplog(const char* cdrbuffer); #include "obj.h" diff --git a/daemon/main.c b/daemon/main.c index 9d9d94d92..fa1ab885d 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -259,7 +259,8 @@ static void options(int *argc, char ***argv) { char *graphitep = NULL; char *redisps = NULL; char *log_facility_s = NULL; - char *log_facility_cdr_s = NULL; + char *log_facility_cdr_s = NULL; + char *log_facility_rtcp_s = NULL; int version = 0; int sip_source = 0; @@ -287,6 +288,7 @@ static void options(int *argc, char ***argv) { { "log-level", 'L', 0, G_OPTION_ARG_INT, (void *)&log_level,"Mask log priorities above this level","INT" }, { "log-facility",0, 0, G_OPTION_ARG_STRING, &log_facility_s, "Syslog facility to use for logging", "daemon|local0|...|local7"}, { "log-facility-cdr",0, 0, G_OPTION_ARG_STRING, &log_facility_cdr_s, "Syslog facility to use for logging CDRs", "daemon|local0|...|local7"}, + { "log-facility-rtcp",0, 0, G_OPTION_ARG_STRING, &log_facility_rtcp_s, "Syslog facility to use for logging RTCP", "daemon|local0|...|local7"}, { "log-stderr", 'E', 0, G_OPTION_ARG_NONE, &_log_stderr, "Log on stderr instead of syslog", NULL }, { "xmlrpc-format",'x', 0, G_OPTION_ARG_INT, &xmlrpc_fmt, "XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only", "INT" }, { "num-threads", 0, 0, G_OPTION_ARG_INT, &num_threads, "Number of worker threads to create", "INT" }, @@ -369,12 +371,19 @@ static void options(int *argc, char ***argv) { } } - if (log_facility_cdr_s) { - if (!parse_log_facility(log_facility_cdr_s, &_log_facility_cdr)) { - print_available_log_facilities(); - die ("Invalid log facility for CDR '%s' (--log-facility-cdr)\n", log_facility_cdr_s); - } - } + if (log_facility_cdr_s) { + if (!parse_log_facility(log_facility_cdr_s, &_log_facility_cdr)) { + print_available_log_facilities(); + die ("Invalid log facility for CDR '%s' (--log-facility-cdr)\n", log_facility_cdr_s); + } + } + + if (log_facility_rtcp_s) { + if (!parse_log_facility(log_facility_rtcp_s, &_log_facility_rtcp)) { + print_available_log_facilities(); + die ("Invalid log facility for RTCP '%s' (--log-facility-rtcp)\n", log_facility_rtcp_s); + } + } if (_log_stderr) { write_log = log_to_stderr; diff --git a/daemon/rtcp.c b/daemon/rtcp.c index aa9bc3e06..434a065e3 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -11,6 +11,7 @@ #include "log.h" #include "rtp.h" #include "crypto.h" +#include "rtcp_xr.h" @@ -26,9 +27,6 @@ #define SRTCP_R_LENGTH 6 #endif - - - #define RTCP_PT_SR 200 /* sender report */ #define RTCP_PT_RR 201 /* receiver report */ #define RTCP_PT_SDES 202 /* source description */ @@ -36,6 +34,7 @@ #define RTCP_PT_APP 204 /* application specific */ #define RTCP_PT_RTPFB 205 /* transport layer feedback message (RTP/AVPF) */ #define RTCP_PT_PSFB 206 /* payload-specific feedback message (RTP/AVPF) */ +#define RTCP_PT_XR 207 #define SDES_TYPE_END 0 #define SDES_TYPE_CNAME 1 @@ -481,3 +480,73 @@ int rtcp_demux_is_rtcp(const str *s) { return 0; return 1; } + +void print_rtcp_common(char** cdrbufcur, const pjmedia_rtcp_common *common) { + *cdrbufcur += sprintf(*cdrbufcur,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", + ntohl(common->version), + ntohl(common->p), + ntohl(common->count), + ntohl(common->pt), + ntohl(common->length), + ntohl(common->ssrc)); +} + +void print_rtcp_sr(char** cdrbufcur, const pjmedia_rtcp_sr* sr) { + *cdrbufcur += sprintf(*cdrbufcur,"ntp_sec=%u, ntp_fractions=%u, rtp_ts=%u, sender_packets=%u, sender_bytes=%u, ", + ntohl(sr->ntp_sec), + ntohl(sr->ntp_frac), + ntohl(sr->rtp_ts), + ntohl(sr->sender_pcount), + ntohl(sr->sender_bcount)); +} + +void print_rtcp_rr(char** cdrbufcur, const pjmedia_rtcp_rr* rr) { + /* Get packet loss */ + u_int32_t packet_loss=0; + packet_loss = (rr->total_lost_2 << 16) + + (rr->total_lost_1 << 8) + + rr->total_lost_0; + + *cdrbufcur += sprintf(*cdrbufcur,"ssrc=%u, fraction_lost=%u, packet_loss=%u, last_seq=%u, jitter=%u, last_sr=%u, delay_since_last_sr=%u, ", + ntohl(rr->ssrc), + ntohl(rr->fract_lost), + ntohl(packet_loss), + ntohl(rr->last_seq), + ntohl(rr->jitter), + ntohl(rr->lsr), + ntohl(rr->dlsr)); +} + +void parse_and_log_rtcp_report(struct stream_fd *sfd, const void *pkt, long size) { + + static const int CDRBUFLENGTH = 1024*1024*1; // 1 MB + char cdrbuffer[CDRBUFLENGTH]; memset(&cdrbuffer,0,CDRBUFLENGTH); + char* cdrbufcur = cdrbuffer; + pjmedia_rtcp_common *common = (pjmedia_rtcp_common*) pkt; + const pjmedia_rtcp_rr *rr = NULL; + const pjmedia_rtcp_sr *sr = NULL; + + cdrbufcur += sprintf(cdrbufcur,"[%s] ",sfd->stream->call->callid); + + print_rtcp_common(&cdrbufcur,common); + + /* Parse RTCP */ + if (common->pt == RTCP_PT_SR) { + sr = (pjmedia_rtcp_sr*) (((char*)pkt) + sizeof(pjmedia_rtcp_common)); + + print_rtcp_sr(&cdrbufcur,sr); + + if (common->count > 0 && size >= (sizeof(pjmedia_rtcp_sr_pkt))) { + rr = (pjmedia_rtcp_rr*)(((char*)pkt) + (sizeof(pjmedia_rtcp_common) + + sizeof(pjmedia_rtcp_sr))); + print_rtcp_rr(&cdrbufcur,rr); + } + } else if (common->pt == RTCP_PT_RR && common->count > 0) { + rr = (pjmedia_rtcp_rr*)(((char*)pkt) + sizeof(pjmedia_rtcp_common)); + print_rtcp_rr(&cdrbufcur,rr); + + } else if (common->pt == RTCP_PT_XR) { + pjmedia_rtcp_xr_rx_rtcp_xr(&cdrbufcur, pkt, size); + } + rtcplog(cdrbuffer); +} diff --git a/daemon/rtcp.h b/daemon/rtcp.h index d6dc353dd..96f88fa8c 100644 --- a/daemon/rtcp.h +++ b/daemon/rtcp.h @@ -2,6 +2,7 @@ #define _RTCP_H_ #include "str.h" +#include "call.h" struct crypto_context; @@ -19,6 +20,83 @@ struct rtcp_packet { u_int32_t ssrc; } __attribute__ ((packed)); +/** + * RTCP sender report. + */ +typedef struct pjmedia_rtcp_sr +{ + u_int32_t ntp_sec; /**< NTP time, seconds part. */ + u_int32_t ntp_frac; /**< NTP time, fractions part. */ + u_int32_t rtp_ts; /**< RTP timestamp. */ + u_int32_t sender_pcount; /**< Sender packet cound. */ + u_int32_t sender_bcount; /**< Sender octet/bytes count. */ +} pjmedia_rtcp_sr; + + +/** + * RTCP receiver report. + */ +typedef struct pjmedia_rtcp_rr +{ + u_int32_t ssrc; /**< SSRC identification. */ +#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 + u_int32_t fract_lost:8; /**< Fraction lost. */ + u_int32_t total_lost_2:8; /**< Total lost, bit 16-23. */ + u_int32_t total_lost_1:8; /**< Total lost, bit 8-15. */ + u_int32_t total_lost_0:8; /**< Total lost, bit 0-7. */ +#else + u_int32_t fract_lost:8; /**< Fraction lost. */ + u_int32_t total_lost_2:8; /**< Total lost, bit 0-7. */ + u_int32_t total_lost_1:8; /**< Total lost, bit 8-15. */ + u_int32_t total_lost_0:8; /**< Total lost, bit 16-23. */ +#endif + u_int32_t last_seq; /**< Last sequence number. */ + u_int32_t jitter; /**< Jitter. */ + u_int32_t lsr; /**< Last SR. */ + u_int32_t dlsr; /**< Delay since last SR. */ +} pjmedia_rtcp_rr; + + +/** + * RTCP common header. + */ +typedef struct pjmedia_rtcp_common +{ +#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 + unsigned version:2; /**< packet type */ + unsigned p:1; /**< padding flag */ + unsigned count:5; /**< varies by payload type */ + unsigned pt:8; /**< payload type */ +#else + unsigned count:5; /**< varies by payload type */ + unsigned p:1; /**< padding flag */ + unsigned version:2; /**< packet type */ + unsigned pt:8; /**< payload type */ +#endif + unsigned length:16; /**< packet length */ + u_int32_t ssrc; /**< SSRC identification */ +} pjmedia_rtcp_common; + +/** + * This structure declares default RTCP packet (SR) that is sent by pjmedia. + * Incoming RTCP packet may have different format, and must be parsed + * manually by application. + */ +typedef struct pjmedia_rtcp_sr_pkt +{ + pjmedia_rtcp_common common; /**< Common header. */ + pjmedia_rtcp_sr sr; /**< Sender report. */ + pjmedia_rtcp_rr rr; /**< variable-length list */ +} pjmedia_rtcp_sr_pkt; + +/** + * This structure declares RTCP RR (Receiver Report) packet. + */ +typedef struct pjmedia_rtcp_rr_pkt +{ + pjmedia_rtcp_common common; /**< Common header. */ + pjmedia_rtcp_rr rr; /**< variable-length list */ +} pjmedia_rtcp_rr_pkt; int rtcp_avpf2avp(str *); @@ -27,6 +105,6 @@ int rtcp_savp2avp(str *, struct crypto_context *); int rtcp_demux_is_rtcp(const str *); - +void parse_and_log_rtcp_report(struct stream_fd *sfd, const void *pkt, long size); #endif diff --git a/daemon/rtcp_xr.c b/daemon/rtcp_xr.c new file mode 100644 index 000000000..9b4bc016b --- /dev/null +++ b/daemon/rtcp_xr.c @@ -0,0 +1,160 @@ +/* + * rtcp_xr.c + * + * Created on: Mar 29, 2015 + * Author: fmetz + */ +#include +#include +#include "rtcp_xr.h" + +/* RTCP XR payload type */ +#define RTCP_XR 207 + +/* RTCP XR block types */ +#define BT_LOSS_RLE 1 +#define BT_DUP_RLE 2 +#define BT_RCPT_TIMES 3 +#define BT_RR_TIME 4 +#define BT_DLRR 5 +#define BT_STATS 6 +#define BT_VOIP_METRICS 7 + + +void print_rtcp_xr_common(char* cdrbufcur,pjmedia_rtcp_xr_pkt *rtcp_xr) { + cdrbufcur += sprintf(cdrbufcur,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", + ntohl(rtcp_xr->common.version), + ntohl(rtcp_xr->common.p), + ntohl(rtcp_xr->common.count), + ntohl(rtcp_xr->common.pt), + ntohl(rtcp_xr->common.length), + ntohl(rtcp_xr->common.ssrc)); +} + +void print_rtcp_xr_rb_header(char* cdrbufcur,pjmedia_rtcp_xr_rb_header *rb_header) { + cdrbufcur += sprintf(cdrbufcur,"rb_header_blocktype=%u, rb_header_blockspecdata=%u, rb_header_blocklength=%u, ", + ntohl(rb_header->bt), + ntohl(rb_header->specific), + ntohl(rb_header->length)); +} + +void print_rtcp_xr_rb_rr_time(char* cdrbufcur,pjmedia_rtcp_xr_rb_rr_time *rb_rr_time) { + print_rtcp_xr_rb_header(cdrbufcur,&rb_rr_time->header); + cdrbufcur += sprintf(cdrbufcur,"rb_rr_time_ntp_sec=%u, rb_rr_time_ntp_frac=%u, ", + ntohl(rb_rr_time->ntp_sec), + ntohl(rb_rr_time->ntp_frac)); +} + +void print_rtcp_xr_rb_dlrr(char* cdrbufcur,pjmedia_rtcp_xr_rb_dlrr *rb_dlrr) { + print_rtcp_xr_rb_header(cdrbufcur,&rb_dlrr->header); + cdrbufcur += sprintf(cdrbufcur,"rb_dlrr_ssrc=%u, rb_dlrr_lrr=%u, rb_dlrr_dlrr=%u, ", + ntohl(rb_dlrr->item.ssrc), + ntohl(rb_dlrr->item.lrr), + ntohl(rb_dlrr->item.dlrr)); +} + +void print_rtcp_xr_rb_stats(char* cdrbufcur,pjmedia_rtcp_xr_rb_stats *rb_stats) { + print_rtcp_xr_rb_header(cdrbufcur,&rb_stats->header); + cdrbufcur += sprintf(cdrbufcur,"rb_stats_ssrc=%u, rb_stats_begin_seq=%u, rb_stats_end_seq=%u, rb_stats_lost_packets=%u, rb_stats_duplicate_packets=%u," + "rb_stats_jitter_min=%u, rb_stats_jitter_max=%u, rb_stats_jitter_mean=%u, rb_stats_jitter_deviation=%u," + "rb_stats_toh_min=%u, rb_stats_toh_max=%u, rb_stats_toh_mean=%u, rb_stats_toh_deviation=%u, ", + ntohl(rb_stats->ssrc), + ntohl(rb_stats->begin_seq), + ntohl(rb_stats->end_seq), + ntohl(rb_stats->lost), + ntohl(rb_stats->dup), + ntohl(rb_stats->jitter_min), + ntohl(rb_stats->jitter_max), + ntohl(rb_stats->jitter_mean), + ntohl(rb_stats->jitter_dev), + ntohl(rb_stats->toh_min), + ntohl(rb_stats->toh_max), + ntohl(rb_stats->toh_mean), + ntohl(rb_stats->toh_dev)); +} + +void print_rtcp_xr_rb_voip_mtc(char* cdrbufcur,pjmedia_rtcp_xr_rb_voip_mtc *rb_voip_mtc) { + print_rtcp_xr_rb_header(cdrbufcur,&rb_voip_mtc->header); + cdrbufcur += sprintf(cdrbufcur,"rb_voip_mtc_ssrc=%u, rb_voip_mtc_loss_rate=%u, rb_voip_mtc_discard_rate=%u, rb_voip_mtc_burst_den=%u, " + "rb_voip_mtc_gap_den=%u, rb_voip_mtc_burst_dur=%u, rb_voip_mtc_gap_dur=%u, rb_voip_mtc_rnd_trip_delay=%u, " + "rb_voip_mtc_end_sys_delay=%u, rb_voip_mtc_signal_lvl=%u, rb_voip_mtc_noise_lvl=%u, rb_voip_mtc_rerl=%u, " + "rb_voip_mtc_gmin=%u, rb_voip_mtc_r_factor=%u, rb_voip_mtc_ext_r_factor=%u, rb_voip_mtc_mos_lq=%u, " + "rb_voip_mtc_mos_cq=%u, rb_voip_mtc_rx_config=%u, rb_voip_mtc_jb_nom=%u, rb_voip_mtc_jb_max=%u, " + "rb_voip_mtc_jb_abs_max=%u, ", + ntohl(rb_voip_mtc->ssrc), + ntohl(rb_voip_mtc->loss_rate), + ntohl(rb_voip_mtc->discard_rate), + ntohl(rb_voip_mtc->burst_den), + ntohl(rb_voip_mtc->gap_den), + ntohl(rb_voip_mtc->burst_dur), + ntohl(rb_voip_mtc->gap_dur), + ntohl(rb_voip_mtc->rnd_trip_delay), + ntohl(rb_voip_mtc->end_sys_delay), + ntohl(rb_voip_mtc->signal_lvl), + ntohl(rb_voip_mtc->noise_lvl), + ntohl(rb_voip_mtc->rerl), + ntohl(rb_voip_mtc->gmin), + ntohl(rb_voip_mtc->r_factor), + ntohl(rb_voip_mtc->ext_r_factor), + ntohl(rb_voip_mtc->mos_lq), + ntohl(rb_voip_mtc->mos_cq), + ntohl(rb_voip_mtc->rx_config), + ntohl(rb_voip_mtc->jb_nom), + ntohl(rb_voip_mtc->jb_max), + ntohl(rb_voip_mtc->jb_abs_max)); +} + +void pjmedia_rtcp_xr_rx_rtcp_xr(char* cdrbufcur, const void *pkt, size_t size) { + + const pjmedia_rtcp_xr_pkt *rtcp_xr = (pjmedia_rtcp_xr_pkt*) pkt; + const pjmedia_rtcp_xr_rb_rr_time *rb_rr_time = NULL; + const pjmedia_rtcp_xr_rb_dlrr *rb_dlrr = NULL; + const pjmedia_rtcp_xr_rb_stats *rb_stats = NULL; + const pjmedia_rtcp_xr_rb_voip_mtc *rb_voip_mtc = NULL; + const pjmedia_rtcp_xr_rb_header *rb_hdr = (pjmedia_rtcp_xr_rb_header*) + rtcp_xr->buf; + unsigned pkt_len, rb_len; + + if (rtcp_xr->common.pt != RTCP_XR) + return; + + print_rtcp_xr_common(cdrbufcur,rtcp_xr); + + pkt_len = ntohs((u_int16_t)rtcp_xr->common.length); + + if ((pkt_len + 1) > (size / 4)) + return; + + /* Parse report rpt_types */ + while ((int32_t*)rb_hdr < (int32_t*)pkt + pkt_len) + { + rb_len = ntohs((u_int16_t)rb_hdr->length); + + /* Just skip any block with length == 0 (no report content) */ + if (rb_len) { + switch (rb_hdr->bt) { + case BT_RR_TIME: + rb_rr_time = (pjmedia_rtcp_xr_rb_rr_time*) rb_hdr; + print_rtcp_xr_rb_rr_time(cdrbufcur,rb_rr_time); + break; + case BT_DLRR: + rb_dlrr = (pjmedia_rtcp_xr_rb_dlrr*) rb_hdr; + print_rtcp_xr_rb_dlrr(cdrbufcur,rb_dlrr); + break; + case BT_STATS: + rb_stats = (pjmedia_rtcp_xr_rb_stats*) rb_hdr; + print_rtcp_xr_rb_stats(cdrbufcur,rb_stats); + break; + case BT_VOIP_METRICS: + rb_voip_mtc = (pjmedia_rtcp_xr_rb_voip_mtc*) rb_hdr; + print_rtcp_xr_rb_voip_mtc(cdrbufcur,rb_voip_mtc); + break; + default: + break; + } + } + rb_hdr = (pjmedia_rtcp_xr_rb_header*) + ((int32_t*)rb_hdr + rb_len + 1); + } +} + diff --git a/daemon/rtcp_xr.h b/daemon/rtcp_xr.h new file mode 100644 index 000000000..b8cbb5b5d --- /dev/null +++ b/daemon/rtcp_xr.h @@ -0,0 +1,229 @@ +/* + * rtcp_xr.h + * + * Created on: Mar 29, 2015 + * Author: fmetz + */ + +#ifndef RTCP_XR_H_ +#define RTCP_XR_H_ + +#include +#include + +/** + * @defgroup PJMED_RTCP_XR RTCP Extended Report (XR) - RFC 3611 + * @ingroup PJMEDIA_SESSION + * @brief RTCP XR extension to RTCP session + * @{ + * + * PJMEDIA implements subsets of RTCP XR specification (RFC 3611) to monitor + * the quality of the real-time media (audio/video) transmission. + */ + +/** + * Enumeration of report types of RTCP XR. Useful for user to enable varying + * combinations of RTCP XR report blocks. + */ +typedef enum { + PJMEDIA_RTCP_XR_LOSS_RLE = (1 << 0), + PJMEDIA_RTCP_XR_DUP_RLE = (1 << 1), + PJMEDIA_RTCP_XR_RCPT_TIMES = (1 << 2), + PJMEDIA_RTCP_XR_RR_TIME = (1 << 3), + PJMEDIA_RTCP_XR_DLRR = (1 << 4), + PJMEDIA_RTCP_XR_STATS = (1 << 5), + PJMEDIA_RTCP_XR_VOIP_METRICS = (1 << 6) +} pjmedia_rtcp_xr_type; + +/** + * Enumeration of info need to be updated manually to RTCP XR. Most info + * could be updated automatically each time RTP received. + */ +typedef enum { + PJMEDIA_RTCP_XR_INFO_SIGNAL_LVL = 1, + PJMEDIA_RTCP_XR_INFO_NOISE_LVL = 2, + PJMEDIA_RTCP_XR_INFO_RERL = 3, + PJMEDIA_RTCP_XR_INFO_R_FACTOR = 4, + PJMEDIA_RTCP_XR_INFO_MOS_LQ = 5, + PJMEDIA_RTCP_XR_INFO_MOS_CQ = 6, + PJMEDIA_RTCP_XR_INFO_CONF_PLC = 7, + PJMEDIA_RTCP_XR_INFO_CONF_JBA = 8, + PJMEDIA_RTCP_XR_INFO_CONF_JBR = 9, + PJMEDIA_RTCP_XR_INFO_JB_NOM = 10, + PJMEDIA_RTCP_XR_INFO_JB_MAX = 11, + PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX = 12 +} pjmedia_rtcp_xr_info; + +/** + * Enumeration of PLC types definitions for RTCP XR report. + */ +typedef enum { + PJMEDIA_RTCP_XR_PLC_UNK = 0, + PJMEDIA_RTCP_XR_PLC_DIS = 1, + PJMEDIA_RTCP_XR_PLC_ENH = 2, + PJMEDIA_RTCP_XR_PLC_STD = 3 +} pjmedia_rtcp_xr_plc_type; + +/** + * Enumeration of jitter buffer types definitions for RTCP XR report. + */ +typedef enum { + PJMEDIA_RTCP_XR_JB_UNKNOWN = 0, + PJMEDIA_RTCP_XR_JB_FIXED = 2, + PJMEDIA_RTCP_XR_JB_ADAPTIVE = 3 +} pjmedia_rtcp_xr_jb_type; + + +#pragma pack(1) + +/** + * This type declares RTCP XR Report Header. + */ +typedef struct pjmedia_rtcp_xr_rb_header +{ + u_int8_t bt; /**< Block type. */ + u_int8_t specific; /**< Block specific data. */ + u_int16_t length; /**< Block length. */ +} pjmedia_rtcp_xr_rb_header; + +/** + * This type declares RTCP XR Receiver Reference Time Report Block. + */ +typedef struct pjmedia_rtcp_xr_rb_rr_time +{ + pjmedia_rtcp_xr_rb_header header; /**< Block header. */ + u_int32_t ntp_sec; /**< NTP time, seconds part. */ + u_int32_t ntp_frac; /**< NTP time, fractions part. */ +} pjmedia_rtcp_xr_rb_rr_time; + + +/** + * This type declares RTCP XR DLRR Report Sub-block + */ +typedef struct pjmedia_rtcp_xr_rb_dlrr_item +{ + u_int32_t ssrc; /**< receiver SSRC */ + u_int32_t lrr; /**< last receiver report */ + u_int32_t dlrr; /**< delay since last receiver + report */ +} pjmedia_rtcp_xr_rb_dlrr_item; + +/** + * This type declares RTCP XR DLRR Report Block + */ +typedef struct pjmedia_rtcp_xr_rb_dlrr +{ + pjmedia_rtcp_xr_rb_header header; /**< Block header. */ + pjmedia_rtcp_xr_rb_dlrr_item item; /**< Block contents, + variable length list */ +} pjmedia_rtcp_xr_rb_dlrr; + +/** + * This type declares RTCP XR Statistics Summary Report Block + */ +typedef struct pjmedia_rtcp_xr_rb_stats +{ + pjmedia_rtcp_xr_rb_header header; /**< Block header. */ + u_int32_t ssrc; /**< Receiver SSRC */ + u_int16_t begin_seq; /**< Begin RTP sequence reported */ + u_int16_t end_seq; /**< End RTP sequence reported */ + u_int32_t lost; /**< Number of packet lost in this + interval */ + u_int32_t dup; /**< Number of duplicated packet in + this interval */ + u_int32_t jitter_min; /**< Minimum jitter in this interval */ + u_int32_t jitter_max; /**< Maximum jitter in this interval */ + u_int32_t jitter_mean; /**< Average jitter in this interval */ + u_int32_t jitter_dev; /**< Jitter deviation in this + interval */ + u_int32_t toh_min:8; /**< Minimum ToH in this interval */ + u_int32_t toh_max:8; /**< Maximum ToH in this interval */ + u_int32_t toh_mean:8; /**< Average ToH in this interval */ + u_int32_t toh_dev:8; /**< ToH deviation in this interval */ +} pjmedia_rtcp_xr_rb_stats; + +/** + * This type declares RTCP XR VoIP Metrics Report Block + */ +typedef struct pjmedia_rtcp_xr_rb_voip_mtc +{ + pjmedia_rtcp_xr_rb_header header; /**< Block header. */ + u_int32_t ssrc; /**< Receiver SSRC */ + u_int8_t loss_rate; /**< Packet loss rate */ + u_int8_t discard_rate; /**< Packet discarded rate */ + u_int8_t burst_den; /**< Burst density */ + u_int8_t gap_den; /**< Gap density */ + u_int16_t burst_dur; /**< Burst duration */ + u_int16_t gap_dur; /**< Gap duration */ + u_int16_t rnd_trip_delay;/**< Round trip delay */ + u_int16_t end_sys_delay; /**< End system delay */ + u_int8_t signal_lvl; /**< Signal level */ + u_int8_t noise_lvl; /**< Noise level */ + u_int8_t rerl; /**< Residual Echo Return Loss */ + u_int8_t gmin; /**< The gap threshold */ + u_int8_t r_factor; /**< Voice quality metric carried + over this RTP session */ + u_int8_t ext_r_factor; /**< Voice quality metric carried + outside of this RTP session*/ + u_int8_t mos_lq; /**< Mean Opinion Score for + Listening Quality */ + u_int8_t mos_cq; /**< Mean Opinion Score for + Conversation Quality */ + u_int8_t rx_config; /**< Receiver configuration */ + u_int8_t reserved2; /**< Not used */ + u_int16_t jb_nom; /**< Current delay by jitter + buffer */ + u_int16_t jb_max; /**< Maximum delay by jitter + buffer */ + u_int16_t jb_abs_max; /**< Maximum possible delay by + jitter buffer */ +} pjmedia_rtcp_xr_rb_voip_mtc; + + +/** + * Constant of RTCP-XR content size. + */ +#define PJMEDIA_RTCP_XR_BUF_SIZE \ + sizeof(pjmedia_rtcp_xr_rb_rr_time) + \ + sizeof(pjmedia_rtcp_xr_rb_dlrr) + \ + sizeof(pjmedia_rtcp_xr_rb_stats) + \ + sizeof(pjmedia_rtcp_xr_rb_voip_mtc) + + +/** + * This structure declares RTCP XR (Extended Report) packet. + */ +typedef struct pjmedia_rtcp_xr_pkt +{ + struct { +#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 + unsigned version:2; /**< packet type */ + unsigned p:1; /**< padding flag */ + unsigned count:5; /**< varies by payload type */ + unsigned pt:8; /**< payload type */ +#else + unsigned count:5; /**< varies by payload type */ + unsigned p:1; /**< padding flag */ + unsigned version:2; /**< packet type */ + unsigned pt:8; /**< payload type */ +#endif + unsigned length:16; /**< packet length */ + u_int32_t ssrc; /**< SSRC identification */ + } common; + + int8_t buf[PJMEDIA_RTCP_XR_BUF_SIZE]; + /**< Content buffer */ +} pjmedia_rtcp_xr_pkt; + + +/** + * This function is called internally by RTCP session when it receives + * incoming RTCP XR packets. + * + * @param rtcp_pkt The received RTCP XR packet. + * @param size Size of the incoming packet. + */ +void pjmedia_rtcp_xr_rx_rtcp_xr( char* cdrbufcur, const void *rtcp_pkt, size_t size); + + +#endif /* RTCP_XR_H_ */ diff --git a/debian/ngcp-rtpengine-daemon.default b/debian/ngcp-rtpengine-daemon.default index 20b10c3d5..8ed12b7ea 100644 --- a/debian/ngcp-rtpengine-daemon.default +++ b/debian/ngcp-rtpengine-daemon.default @@ -21,6 +21,7 @@ TABLE=0 # LOG_LEVEL=6 # LOG_FACILITY=daemon # LOG_FACILITY_CDR=daemon +# LOG_FACILITY_RTCP=daemon # NUM_THREADS=5 # DELETE_DELAY=30 # GRAPHITE=9006 diff --git a/debian/ngcp-rtpengine-daemon.init b/debian/ngcp-rtpengine-daemon.init index 1c7e96f5c..30808d327 100755 --- a/debian/ngcp-rtpengine-daemon.init +++ b/debian/ngcp-rtpengine-daemon.init @@ -70,6 +70,7 @@ OPTIONS="$OPTIONS --table=$TABLE" [ -z "$LOG_LEVEL" ] || OPTIONS="$OPTIONS --log-level=$LOG_LEVEL" [ -z "$LOG_FACILITY" ] || OPTIONS="$OPTIONS --log-facility=$LOG_FACILITY" [ -z "$LOG_FACILITY_CDR" ] || OPTIONS="$OPTIONS --log-facility-cdr=$LOG_FACILITY_CDR" +[ -z "$LOG_FACILITY_RTCP" ] || OPTIONS="$OPTIONS --log-facility-rtcp=$LOG_FACILITY_RTCP" [ -z "$NUM_THREADS" ] || OPTIONS="$OPTIONS --num-threads=$NUM_THREADS" [ -z "$DELETE_DELAY" ] || OPTIONS="$OPTIONS --delete-delay=$DELETE_DELAY" [ -z "$GRAPHITE" ] || OPTIONS="$OPTIONS --graphite=$GRAPHITE" diff --git a/el/rtpengine.init b/el/rtpengine.init index 1fb33ce62..9320696d9 100644 --- a/el/rtpengine.init +++ b/el/rtpengine.init @@ -157,6 +157,11 @@ build_opts() { then OPTS+=" --log-facility-cdr=$LOG_FACILITY_CDR" fi + + if [[ -n "$LOG_FACILITY_RTCP" ]] + then + OPTS+=" --log-facility-rtcp=$LOG_FACILITY_RTCP" + fi } start() { From f8aaf358cd7740b93dd77586f4e3c93801af8e1d Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Fri, 10 Apr 2015 18:30:03 +0200 Subject: [PATCH 10/13] Implemented TOS/Traffic Class bit in received first RTP packet --- daemon/call.c | 20 ++++++++++++++++---- daemon/call.h | 1 + kernel-module/xt_RTPENGINE.c | 16 ++++++++++------ kernel-module/xt_RTPENGINE.h | 1 + 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 96321c945..5f374f5b7 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "poller.h" #include "aux.h" @@ -1347,6 +1348,10 @@ static void callmaster_timer(void *ptr) { DS(bytes); DS(errors); + mutex_lock(&m->statspslock); + ps->stats.in_tos_tclass = m->statsps.in_tos_tclass = ke->stats.in_tos; + mutex_unlock(&m->statspslock); + #if (RE_HAS_MEASUREDELAY) mutex_lock(&m->statspslock); ps->stats.delay_min = m->statsps.delay_min = ke->stats.delay_min; @@ -1363,6 +1368,7 @@ static void callmaster_timer(void *ptr) { ps->kernel_stats.packets = ke->stats.packets; ps->kernel_stats.bytes = ke->stats.bytes; ps->kernel_stats.errors = ke->stats.errors; + ps->kernel_stats.in_tos_tclass = ke->stats.in_tos; #if (RE_HAS_MEASUREDELAY) ps->kernel_stats.delay_min = ke->stats.delay_min; @@ -2512,14 +2518,16 @@ void call_destroy(struct call *c) { "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_last_packet=%llu, " + "ml%i_midx%u_%s_in_tos_tclass=%" PRIu8 ", ", 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->last_packet, + cdrlinecnt, md->index, protocol, ((unsigned int) ps->stats.in_tos_tclass) & 0xff); } else { #if (RE_HAS_MEASUREDELAY) cdrbufcur += sprintf(cdrbufcur, @@ -2530,6 +2538,7 @@ void call_destroy(struct call *c) { "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_in_tos_tclass=%" PRIu8 ", " "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, ", @@ -2540,6 +2549,7 @@ void call_destroy(struct call *c) { 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 int) ps->stats.in_tos_tclass) & 0xff, 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); @@ -2551,14 +2561,16 @@ void call_destroy(struct call *c) { "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_last_packet=%llu, " + "ml%i_midx%u_%s_in_tos_tclass=%" PRIu8 ", ", 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->last_packet, + cdrlinecnt, md->index, protocol, ((unsigned int) ps->stats.in_tos_tclass) & 0xff); #endif } } diff --git a/daemon/call.h b/daemon/call.h index 8960de9df..fffd4d72f 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -193,6 +193,7 @@ struct stats { struct timespec delay_min; struct timespec delay_avg; struct timespec delay_max; + u_int8_t in_tos_tclass; }; struct totalstats { diff --git a/kernel-module/xt_RTPENGINE.c b/kernel-module/xt_RTPENGINE.c index 5b9ece7f2..6f0a3d1b9 100644 --- a/kernel-module/xt_RTPENGINE.c +++ b/kernel-module/xt_RTPENGINE.c @@ -2146,9 +2146,9 @@ static int re_timespec_cmp (struct timespec *a, struct timespec *b) } #if (RE_HAS_MEASUREDELAY) - 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 timespec *starttime, u_int8_t in_tos) { #else - 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, u_int8_t in_tos) { #endif struct udphdr *uh; struct rtpengine_target *g; @@ -2263,6 +2263,9 @@ not_rtp: out: spin_lock_irqsave(&g->stats_lock, flags); + if (g->stats.packets==0) + g->stats.in_tos = in_tos; + if (err) g->stats.errors++; else { @@ -2351,9 +2354,9 @@ static unsigned int rtpengine4(struct sk_buff *oskb, const struct xt_action_para src.u.ipv4 = ih->saddr; #if (RE_HAS_MEASUREDELAY) - return rtpengine46(skb, t, &src, &starttime); + return rtpengine46(skb, t, &src, &starttime, (u_int8_t)ih->tos); #else - return rtpengine46(skb, t, &src); + return rtpengine46(skb, t, &src, (u_int8_t)ih->tos); #endif skip2: @@ -2393,6 +2396,7 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para skb_reset_network_header(skb); ih = ipv6_hdr(skb); + skb_pull(skb, sizeof(*ih)); if (ih->nexthdr != IPPROTO_UDP) goto skip2; @@ -2402,9 +2406,9 @@ static unsigned int rtpengine6(struct sk_buff *oskb, const struct xt_action_para memcpy(&src.u.ipv6, &ih->saddr, sizeof(src.u.ipv6)); #if (RE_HAS_MEASUREDELAY) - return rtpengine46(skb, t, &src, &starttime); + return rtpengine46(skb, t, &src, &starttime, ipv6_get_dsfield(ih)); #else - return rtpengine46(skb, t, &src); + return rtpengine46(skb, t, &src, ipv6_get_dsfield(ih)); #endif skip2: diff --git a/kernel-module/xt_RTPENGINE.h b/kernel-module/xt_RTPENGINE.h index 6ba4fed32..868b6ed06 100644 --- a/kernel-module/xt_RTPENGINE.h +++ b/kernel-module/xt_RTPENGINE.h @@ -12,6 +12,7 @@ struct rtpengine_stats { struct timespec delay_min; struct timespec delay_avg; struct timespec delay_max; + u_int8_t in_tos; }; struct re_address { From 8a0fbf201f3ff79c5bf048a00bcd127c5446157e Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Tue, 14 Apr 2015 18:59:06 +0200 Subject: [PATCH 11/13] Fixed RTCP parsing of bitfield structs. --- daemon/rtcp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 434a065e3..f3e8973dc 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -483,11 +483,11 @@ int rtcp_demux_is_rtcp(const str *s) { void print_rtcp_common(char** cdrbufcur, const pjmedia_rtcp_common *common) { *cdrbufcur += sprintf(*cdrbufcur,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", - ntohl(common->version), - ntohl(common->p), - ntohl(common->count), - ntohl(common->pt), - ntohl(common->length), + common->version, + common->p, + common->count, + common->pt, + common->length, ntohl(common->ssrc)); } From 1d1b8f21ce840a2643d2d64382c63a68c42041b5 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Wed, 15 Apr 2015 06:54:52 +0200 Subject: [PATCH 12/13] Fixed RTCP Parsing also for XR reports. --- daemon/rtcp_xr.c | 58 ++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/daemon/rtcp_xr.c b/daemon/rtcp_xr.c index 9b4bc016b..7aa61da8c 100644 --- a/daemon/rtcp_xr.c +++ b/daemon/rtcp_xr.c @@ -23,19 +23,19 @@ void print_rtcp_xr_common(char* cdrbufcur,pjmedia_rtcp_xr_pkt *rtcp_xr) { cdrbufcur += sprintf(cdrbufcur,"version=%u, padding=%u, count=%u, payloadtype=%u, length=%u, ssrc=%u, ", - ntohl(rtcp_xr->common.version), - ntohl(rtcp_xr->common.p), - ntohl(rtcp_xr->common.count), - ntohl(rtcp_xr->common.pt), - ntohl(rtcp_xr->common.length), + rtcp_xr->common.version, + rtcp_xr->common.p, + rtcp_xr->common.count, + rtcp_xr->common.pt, + rtcp_xr->common.length, ntohl(rtcp_xr->common.ssrc)); } void print_rtcp_xr_rb_header(char* cdrbufcur,pjmedia_rtcp_xr_rb_header *rb_header) { cdrbufcur += sprintf(cdrbufcur,"rb_header_blocktype=%u, rb_header_blockspecdata=%u, rb_header_blocklength=%u, ", - ntohl(rb_header->bt), - ntohl(rb_header->specific), - ntohl(rb_header->length)); + rb_header->bt, + rb_header->specific, + ntohs(rb_header->length)); } void print_rtcp_xr_rb_rr_time(char* cdrbufcur,pjmedia_rtcp_xr_rb_rr_time *rb_rr_time) { @@ -59,7 +59,7 @@ void print_rtcp_xr_rb_stats(char* cdrbufcur,pjmedia_rtcp_xr_rb_stats *rb_stats) "rb_stats_jitter_min=%u, rb_stats_jitter_max=%u, rb_stats_jitter_mean=%u, rb_stats_jitter_deviation=%u," "rb_stats_toh_min=%u, rb_stats_toh_max=%u, rb_stats_toh_mean=%u, rb_stats_toh_deviation=%u, ", ntohl(rb_stats->ssrc), - ntohl(rb_stats->begin_seq), + ntohs(rb_stats->begin_seq), ntohl(rb_stats->end_seq), ntohl(rb_stats->lost), ntohl(rb_stats->dup), @@ -82,26 +82,26 @@ void print_rtcp_xr_rb_voip_mtc(char* cdrbufcur,pjmedia_rtcp_xr_rb_voip_mtc *rb_v "rb_voip_mtc_mos_cq=%u, rb_voip_mtc_rx_config=%u, rb_voip_mtc_jb_nom=%u, rb_voip_mtc_jb_max=%u, " "rb_voip_mtc_jb_abs_max=%u, ", ntohl(rb_voip_mtc->ssrc), - ntohl(rb_voip_mtc->loss_rate), - ntohl(rb_voip_mtc->discard_rate), - ntohl(rb_voip_mtc->burst_den), - ntohl(rb_voip_mtc->gap_den), - ntohl(rb_voip_mtc->burst_dur), - ntohl(rb_voip_mtc->gap_dur), - ntohl(rb_voip_mtc->rnd_trip_delay), - ntohl(rb_voip_mtc->end_sys_delay), - ntohl(rb_voip_mtc->signal_lvl), - ntohl(rb_voip_mtc->noise_lvl), - ntohl(rb_voip_mtc->rerl), - ntohl(rb_voip_mtc->gmin), - ntohl(rb_voip_mtc->r_factor), - ntohl(rb_voip_mtc->ext_r_factor), - ntohl(rb_voip_mtc->mos_lq), - ntohl(rb_voip_mtc->mos_cq), - ntohl(rb_voip_mtc->rx_config), - ntohl(rb_voip_mtc->jb_nom), - ntohl(rb_voip_mtc->jb_max), - ntohl(rb_voip_mtc->jb_abs_max)); + rb_voip_mtc->loss_rate, + rb_voip_mtc->discard_rate, + rb_voip_mtc->burst_den, + rb_voip_mtc->gap_den, + ntohs(rb_voip_mtc->burst_dur), + ntohs(rb_voip_mtc->gap_dur), + ntohs(rb_voip_mtc->rnd_trip_delay), + ntohs(rb_voip_mtc->end_sys_delay), + rb_voip_mtc->signal_lvl, + rb_voip_mtc->noise_lvl, + rb_voip_mtc->rerl, + rb_voip_mtc->gmin, + rb_voip_mtc->r_factor, + rb_voip_mtc->ext_r_factor, + rb_voip_mtc->mos_lq, + rb_voip_mtc->mos_cq, + rb_voip_mtc->rx_config, + ntohs(rb_voip_mtc->jb_nom), + ntohs(rb_voip_mtc->jb_max), + ntohs(rb_voip_mtc->jb_abs_max)); } void pjmedia_rtcp_xr_rx_rtcp_xr(char* cdrbufcur, const void *pkt, size_t size) { From cb85cbf44f3d5f2d23420c2b3e204c4fe09500a5 Mon Sep 17 00:00:00 2001 From: Frederic-Philippe Metz Date: Tue, 21 Apr 2015 16:15:16 +0200 Subject: [PATCH 13/13] Fixed wrong Zeroing of stats member --- daemon/graphite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/graphite.c b/daemon/graphite.c index 4ead81427..14fcd1bb1 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -146,8 +146,8 @@ int send_graphite_data() { mutex_lock(&cm->totalstats_interval.total_average_lock); ts.total_average_call_dur = cm->totalstats_interval.total_average_call_dur; ts.total_managed_sess = cm->totalstats_interval.total_managed_sess; - ZERO(ts.total_average_call_dur); - ZERO(ts.total_managed_sess); + ZERO(cm->totalstats_interval.total_average_call_dur); + ZERO(cm->totalstats_interval.total_managed_sess); mutex_unlock(&cm->totalstats_interval.total_average_lock); if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; }