diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-10-18 21:14:15 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-10-18 21:14:15 +0000 |
commit | c61117b370a809a88e79d3e64b1c65848f5fc282 (patch) | |
tree | 174e7d98ac25b2d4f7fe2ea4d988326c57c3239a | |
parent | 64f666bdcb2403922ba264a93b7c95bde6095e25 (diff) |
Add support for setting the maximum trunk size for IAX2 trunking
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@86371 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_iax2.c | 85 | ||||
-rw-r--r-- | configs/iax.conf.sample | 9 |
2 files changed, 94 insertions, 0 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index b9ab341e7..9151f5107 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -141,6 +141,15 @@ static struct ast_codec_pref prefs; static const char tdesc[] = "Inter Asterisk eXchange Driver (Ver 2)"; + +/*! \brief Maximum transimission unit for the UDP packet in the trunk not to be + fragmented. This is based on 1516 - ethernet - ip - udp - iax minus one g711 frame = 1240 */ +#define MAX_TRUNK_MTU 1240 + +static int global_max_trunk_mtu; /*!< Maximum MTU, 0 if not used */ +static int trunk_timed, trunk_untimed, trunk_maxmtu, trunk_nmaxmtu ; /*!< Trunk MTU statistics */ + + static char context[80] = "default"; static char language[MAX_LANGUAGE] = ""; @@ -375,6 +384,7 @@ static struct iax2_trunk_peer { unsigned char *trunkdata; unsigned int trunkdatalen; unsigned int trunkdataalloc; + int trunkmaxmtu; struct iax2_trunk_peer *next; int trunkerror; int calls; @@ -831,6 +841,7 @@ static int iax2_sendtext(struct ast_channel *c, const char *text); static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen); static int iax2_transfer(struct ast_channel *c, const char *dest); static int iax2_write(struct ast_channel *c, struct ast_frame *f); +static int send_trunk(struct iax2_trunk_peer *tpeer, struct timeval *now); static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int); static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int); static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int); @@ -2323,11 +2334,44 @@ static int iax2_show_stats(int fd, int argc, char *argv[]) ast_cli(fd, " IAX Statistics\n"); ast_cli(fd, "---------------------\n"); ast_cli(fd, "Outstanding frames: %d (%d ingress, %d egress)\n", iax_get_frames(), iax_get_iframes(), iax_get_oframes()); + ast_cli(fd, "%d timed and %d untimed transmits; MTU %d/%d/%d\n", trunk_timed, trunk_untimed, + trunk_maxmtu, trunk_nmaxmtu, global_max_trunk_mtu); + ast_cli(fd, "Packets in transmit queue: %d dead, %d final, %d total\n\n", dead, final, cnt); + + trunk_timed = trunk_untimed = 0; + if (trunk_maxmtu > trunk_nmaxmtu) + trunk_nmaxmtu = trunk_maxmtu; return RESULT_SUCCESS; } +/*! \brief Set trunk MTU from CLI */ +static int iax2_set_mtu(int fd, int argc, char *argv[]) +{ + int mtuv; + + if (argc != 4) + return RESULT_SHOWUSAGE; + if (strncasecmp(argv[3], "default", strlen(argv[3])) == 0) + mtuv = MAX_TRUNK_MTU; + else + mtuv = atoi(argv[3]); + + if (mtuv == 0) { + ast_cli(fd, "Trunk MTU control disabled (mtu was %d)\n", global_max_trunk_mtu); + global_max_trunk_mtu = 0; + return RESULT_SUCCESS; + } + if (mtuv < 172 || mtuv > 4000) { + ast_cli(fd, "Trunk MTU must be between 172 and 4000\n"); + return RESULT_SHOWUSAGE; + } + ast_cli(fd, "Trunk MTU changed from %d to %d\n", global_max_trunk_mtu, mtuv); + global_max_trunk_mtu = mtuv; + return RESULT_SUCCESS; +} + static int iax2_show_cache(int fd, int argc, char *argv[]) { struct iax2_dpcache *dp; @@ -3813,6 +3857,8 @@ static int iax2_trunk_queue(struct chan_iax2_pvt *pvt, struct iax_frame *fr) struct ast_frame *f; struct iax2_trunk_peer *tpeer; void *tmp, *ptr; + struct timeval now; + int res; struct ast_iax2_meta_trunk_entry *met; struct ast_iax2_meta_trunk_mini *mtm; @@ -3860,6 +3906,18 @@ static int iax2_trunk_queue(struct chan_iax2_pvt *pvt, struct iax_frame *fr) tpeer->trunkdatalen += f->datalen; tpeer->calls++; + + /* track the largest mtu we actually have sent */ + if (tpeer->trunkdatalen + f->datalen + 4 > trunk_maxmtu) + trunk_maxmtu = tpeer->trunkdatalen + f->datalen + 4 ; + + /* if we have enough for a full MTU, ship it now without waiting */ + if (global_max_trunk_mtu > 0 && tpeer->trunkdatalen + f->datalen + 4 >= global_max_trunk_mtu) { + gettimeofday(&now, NULL); + res = send_trunk(tpeer, &now); + trunk_untimed ++; + } + ast_mutex_unlock(&tpeer->lock); } return 0; @@ -6295,6 +6353,7 @@ static int timing_read(int *id, int fd, short events, void *cbdata) drop = tpeer; } else { res = send_trunk(tpeer, &now); + trunk_timed++; if (iaxtrunkdebug) ast_verbose(" - Trunk peer (%s:%d) has %d call chunk%s in transit, %d bytes backloged and has hit a high water mark of %d bytes\n", ast_inet_ntoa(tpeer->addr.sin_addr), ntohs(tpeer->addr.sin_port), res, (res != 1) ? "s" : "", tpeer->trunkdatalen, tpeer->trunkdataalloc); } @@ -9470,6 +9529,7 @@ static int set_config(char *config_file, int reload) int format; int portno = IAX_DEFAULT_PORTNO; int x; + int mtuv; struct iax2_user *user; struct iax2_peer *peer; struct ast_netsock *ns; @@ -9635,6 +9695,15 @@ static int set_config(char *config_file, int reload) trunkfreq = atoi(v->value); if (trunkfreq < 10) trunkfreq = 10; + } else if (!strcasecmp(v->name, "trunkmtu")) { + mtuv = atoi(v->value); + if (mtuv == 0 ) + global_max_trunk_mtu = 0; + else if (mtuv >= 172 && mtuv < 4000) + global_max_trunk_mtu = mtuv; + else + ast_log(LOG_NOTICE, "trunkmtu value out of bounds (%d) at line %d\n", + mtuv, v->lineno); } else if (!strcasecmp(v->name, "autokill")) { if (sscanf(v->value, "%d", &x) == 1) { if (x >= 0) @@ -9832,6 +9901,7 @@ static int reload_config(void) strcpy(language, ""); strcpy(mohinterpret, "default"); strcpy(mohsuggest, ""); + global_max_trunk_mtu = MAX_TRUNK_MTU; amaflags = 0; delayreject = 0; ast_clear_flag((&globalflags), IAX_NOTRANSFER); @@ -9842,6 +9912,10 @@ static int reload_config(void) set_config(config, 1); prune_peers(); prune_users(); + + trunk_timed = trunk_untimed = 0; + trunk_nmaxmtu = trunk_maxmtu = 0; + AST_LIST_LOCK(®istrations); AST_LIST_TRAVERSE(®istrations, reg, entry) iax2_do_register(reg); @@ -10342,6 +10416,13 @@ static char show_stats_usage[] = "Usage: iax2 show stats\n" " Display statistics on IAX channel driver.\n"; +static char set_mtu_usage[] = +"Usage: iax2 set mtu <value>\n" +" Set the system-wide IAX IP mtu to <value> bytes net or zero to disable.\n" +" Disabling means that the operating system must handle fragmentation of UDP packets\n" +" when the IAX2 trunk packet exceeds the UDP payload size.\n" +" This is substantially below the IP mtu. Try 1240 on ethernets.\n" +" Must be 172 or greater for G.711 samples.\n"; static char show_cache_usage[] = "Usage: iax2 show cache\n" " Display currently cached IAX Dialplan results.\n"; @@ -10496,6 +10577,10 @@ static struct ast_cli_entry cli_iax2[] = { iax2_show_threads, "Display IAX helper thread info", show_threads_usage, NULL, }, + { { "iax2", "set", "mtu", NULL }, + iax2_set_mtu, "Set the IAX systemwide trunking MTU", + set_mtu_usage, NULL, NULL }, + { { "iax2", "show", "users", NULL }, iax2_show_users, "List defined IAX users", show_users_usage, NULL, }, diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample index d9c613bfc..c8b12fae5 100644 --- a/configs/iax.conf.sample +++ b/configs/iax.conf.sample @@ -152,7 +152,16 @@ forcejitterbuffer=no ; minregexpire = 60 ; maxregexpire = 60 ; +; With a large amount of traffic on IAX2 trunks, there is a risk of bad voice quality due to +; the fact that the IAX2 trunking scheme depends on the Linux system to handle fragmentation of +; UDP packets. This may not be very efficient. +; This setting sets the maximum transmission unit for IAX2 UDP trunking. +; default is 1240 bytes. Zero disables this functionality and let's the O/S handle fragmentation. +; +; trunkmtu = 0 +; ; IAX helper threads + ; Establishes the number of iax helper threads to handle I/O. ; iaxthreadcount = 10 ; Establishes the number of extra dynamic threads that may be spawned to handle I/O |