dect
/
asterisk
Archived
13
0
Fork 0

improve IP TOS support for SIP and IAX2 (issue #6355, code from jcollie plus modifications)

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@15435 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
kpfleming 2006-03-28 03:28:52 +00:00
parent 0d346196f9
commit 7c697789d6
9 changed files with 201 additions and 59 deletions

81
acl.c
View File

@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@ -252,12 +252,55 @@ int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *se
return 0;
}
int ast_str2tos(const char *value, int *tos)
struct dscp_codepoint {
char *name;
unsigned int space;
};
/* IANA registered DSCP codepoints */
static const struct dscp_codepoint dscp_pool1[] = {
{ "CS0", 0x00 },
{ "CS1", 0x08 },
{ "CS2", 0x10 },
{ "CS3", 0x18 },
{ "CS4", 0x20 },
{ "CS5", 0x28 },
{ "CS6", 0x30 },
{ "CS7", 0x38 },
{ "AF11", 0x0A },
{ "AF12", 0x0C },
{ "AF13", 0x0E },
{ "AF21", 0x12 },
{ "AF22", 0x14 },
{ "AF23", 0x16 },
{ "AF31", 0x1A },
{ "AF32", 0x1C },
{ "AF33", 0x1E },
{ "AF41", 0x22 },
{ "AF42", 0x24 },
{ "AF43", 0x26 },
{ "EF", 0x2E },
};
int ast_str2tos(const char *value, unsigned int *tos)
{
int fval;
if (sscanf(value, "%i", &fval) == 1)
*tos = fval & 0xff;
else if (!strcasecmp(value, "lowdelay"))
unsigned int x;
if (sscanf(value, "%i", &fval) == 1) {
*tos = fval & 0xFF;
return 0;
}
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
if (!strcasecmp(value, dscp_pool1[x].name)) {
*tos = dscp_pool1[x].space << 2;
return 0;
}
}
if (!strcasecmp(value, "lowdelay"))
*tos = IPTOS_LOWDELAY;
else if (!strcasecmp(value, "throughput"))
*tos = IPTOS_THROUGHPUT;
@ -269,9 +312,37 @@ int ast_str2tos(const char *value, int *tos)
*tos = 0;
else
return -1;
ast_log(LOG_WARNING, "tos value %s is deprecated. See doc/iptos.txt for more information.", value);
return 0;
}
const char *ast_tos2str(unsigned int tos)
{
unsigned int x;
switch (tos) {
case 0:
return "none";
case IPTOS_LOWDELAY:
return "lowdelay";
case IPTOS_THROUGHPUT:
return "throughput";
case IPTOS_RELIABILITY:
return "reliability";
case IPTOS_MINCOST:
return "mincost";
default:
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
if (dscp_pool1[x].space == (tos >> 2))
return dscp_pool1[x].name;
}
}
return "unknown";
}
int ast_get_ip(struct sockaddr_in *sin, const char *value)
{
return ast_get_ip_or_srv(sin, value, NULL);

View File

@ -9040,7 +9040,7 @@ static int set_config(char *config_file, int reload)
tosval = ast_variable_retrieve(cfg, "general", "tos");
if (tosval) {
if (ast_str2tos(tosval, &tos))
ast_log(LOG_WARNING, "Invalid tos value, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n");
ast_log(LOG_WARNING, "Invalid tos value, see doc/iptos.txt for more information.\n");
}
while(v) {
if (!strcasecmp(v->name, "bindport")){
@ -9190,7 +9190,7 @@ static int set_config(char *config_file, int reload)
ast_context_create(NULL, regcontext, "IAX2");
} else if (!strcasecmp(v->name, "tos")) {
if (ast_str2tos(v->value, &tos))
ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/iptos.txt for more information.'\n", v->lineno);
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(accountcode, v->value, sizeof(accountcode));
} else if (!strcasecmp(v->name, "amaflags")) {

View File

@ -364,7 +364,9 @@ static const struct cfsip_options {
#define DEFAULT_ALLOWGUEST TRUE
#define DEFAULT_SRVLOOKUP FALSE /*!< Recommended setting is ON */
#define DEFAULT_COMPACTHEADERS FALSE
#define DEFAULT_TOS FALSE
#define DEFAULT_TOS_SIP 0 /*!< Call signalling packets should be marked as DSCP CS3, but the default is 0 to be compatible with previous versions. */
#define DEFAULT_TOS_AUDIO 0 /*!< Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions. */
#define DEFAULT_TOS_VIDEO 0 /*!< Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions. */
#define DEFAULT_ALLOW_EXT_DOM TRUE
#define DEFAULT_REALM "asterisk"
#define DEFAULT_NOTIFYRINGING TRUE
@ -408,7 +410,9 @@ static int global_allowguest; /*!< allow unauthenticated users/peers to connect
static int global_allowsubscribe; /*!< Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE
the global setting is in globals_flag_page2 */
static int global_mwitime; /*!< Time between MWI checks for peers */
static int global_tos; /*!< IP Type of service */
static int global_tos_sip; /*!< IP type of service for SIP packets */
static int global_tos_audio; /*!< IP type of service for audio RTP packets */
static int global_tos_video; /*!< IP type of service for video RTP packets */
static int compactheaders; /*!< send compact sip headers */
static int recordhistory; /*!< Record SIP history. Off by default */
static int dumphistory; /*!< Dump history to verbose before destroying SIP dialog */
@ -3274,9 +3278,9 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
free(p);
return NULL;
}
ast_rtp_settos(p->rtp, global_tos);
ast_rtp_settos(p->rtp, global_tos_audio);
if (p->vrtp)
ast_rtp_settos(p->vrtp, global_tos);
ast_rtp_settos(p->vrtp, global_tos_video);
p->rtptimeout = global_rtptimeout;
p->rtpholdtimeout = global_rtpholdtimeout;
p->rtpkeepalive = global_rtpkeepalive;
@ -8449,7 +8453,9 @@ static int sip_show_settings(int fd, int argc, char *argv[])
ast_cli(fd, " From: Domain: %s\n", default_fromdomain);
ast_cli(fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off");
ast_cli(fd, " Call Events: %s\n", global_callevents ? "On" : "Off");
ast_cli(fd, " IP ToS: 0x%x\n", global_tos);
ast_cli(fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip));
ast_cli(fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio));
ast_cli(fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video));
#ifdef OSP_SUPPORT
ast_cli(fd, " OSP Support: Yes\n");
#else
@ -12559,6 +12565,7 @@ static int reload_config(enum channelreloadreason reason)
int auto_sip_domains = FALSE;
struct sockaddr_in old_bindaddr = bindaddr;
int registry_count = 0, peer_count = 0, user_count = 0;
int temp_tos = 0;
struct ast_flags debugflag = {0};
cfg = ast_config_load(config);
@ -12585,7 +12592,9 @@ static int reload_config(enum channelreloadreason reason)
outboundproxyip.sin_family = AF_INET; /* Type of address: IPv4 */
ourport = DEFAULT_SIP_PORT;
srvlookup = DEFAULT_SRVLOOKUP;
global_tos = DEFAULT_TOS;
global_tos_sip = DEFAULT_TOS_SIP;
global_tos_audio = DEFAULT_TOS_AUDIO;
global_tos_video = DEFAULT_TOS_VIDEO;
externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */
externexpire = 0; /* Expiration for DNS re-issuing */
externrefresh = 10;
@ -12808,8 +12817,22 @@ static int reload_config(enum channelreloadreason reason)
if (sip_register(v->value, v->lineno) == 0)
registry_count++;
} else if (!strcasecmp(v->name, "tos")) {
if (ast_str2tos(v->value, &global_tos))
ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
if (!ast_str2tos(v->value, &temp_tos)) {
global_tos_sip = temp_tos;
global_tos_audio = temp_tos;
global_tos_video = temp_tos;
ast_log(LOG_WARNING, "tos value at line %d is deprecated. See doc/iptos.txt for more information.", v->lineno);
} else
ast_log(LOG_WARNING, "Invalid tos value at line %d, See doc/iptos.txt for more information.\n", v->lineno);
} else if (!strcasecmp(v->name, "tos_sip")) {
if (ast_str2tos(v->value, &global_tos_sip))
ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, recommended value is 'cs3'. See doc/iptos.txt.\n", v->lineno);
} else if (!strcasecmp(v->name, "tos_audio")) {
if (ast_str2tos(v->value, &global_tos_audio))
ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, recommended value is 'ef'. See doc/iptos.txt.\n", v->lineno);
} else if (!strcasecmp(v->name, "tos_video")) {
if (ast_str2tos(v->value, &global_tos_video))
ast_log(LOG_WARNING, "Invalid tos_video value at line %d, recommended value is 'af41'. See doc/iptos.txt.\n", v->lineno);
} else if (!strcasecmp(v->name, "bindport")) {
if (sscanf(v->value, "%d", &ourport) == 1) {
bindaddr.sin_port = htons(ourport);
@ -12922,10 +12945,10 @@ static int reload_config(enum channelreloadreason reason)
if (option_verbose > 1) {
ast_verbose(VERBOSE_PREFIX_2 "SIP Listening on %s:%d\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port));
ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", global_tos);
ast_verbose(VERBOSE_PREFIX_2 "Using SIP TOS: %s\n", ast_tos2str(global_tos_sip));
}
if (setsockopt(sipsock, IPPROTO_IP, IP_TOS, &global_tos, sizeof(global_tos)))
ast_log(LOG_WARNING, "Unable to set TOS to %d\n", global_tos);
if (setsockopt(sipsock, IPPROTO_IP, IP_TOS, &global_tos_sip, sizeof(global_tos_sip)))
ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global_tos_sip));
}
}
}

View File

@ -46,6 +46,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/md5.h"
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
#include "asterisk/acl.h"
#include "iax2.h"
#include "iax2-provision.h"
#include "iax2-parser.h"
@ -328,20 +329,8 @@ static int iax_template_parse(struct iax_template *cur, struct ast_config *cfg,
} else
ast_log(LOG_WARNING, "Ignoring invalid codec '%s' for '%s' at line %d\n", v->value, s, v->lineno);
} else if (!strcasecmp(v->name, "tos")) {
if (sscanf(v->value, "%d", &x) == 1)
cur->tos = x & 0xff;
else if (!strcasecmp(v->value, "lowdelay"))
cur->tos = IPTOS_LOWDELAY;
else if (!strcasecmp(v->value, "throughput"))
cur->tos = IPTOS_THROUGHPUT;
else if (!strcasecmp(v->value, "reliability"))
cur->tos = IPTOS_RELIABILITY;
else if (!strcasecmp(v->value, "mincost"))
cur->tos = IPTOS_MINCOST;
else if (!strcasecmp(v->value, "none"))
cur->tos = 0;
else
ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
if (ast_str2tos(v->value, &cur->tos))
ast_log(LOG_WARNING, "Invalid tos value at line %d, see doc/iptos.txt for more information.\n", v->lineno);
} else if (!strcasecmp(v->name, "user")) {
strncpy(cur->user, v->value, sizeof(cur->user) - 1);
if (strcmp(cur->user, v->value))
@ -453,7 +442,7 @@ static int iax_show_provisioning(int fd, int argc, char *argv[])
ast_cli(fd, "Alternate: %s\n", iax_server(iabuf, sizeof(iabuf), cur->altserver));
ast_cli(fd, "Flags: %s\n", iax_provflags2str(iabuf, sizeof(iabuf), cur->flags));
ast_cli(fd, "Format: %s\n", ast_getformatname(cur->format));
ast_cli(fd, "TOS: %d\n", cur->tos);
ast_cli(fd, "TOS: 0x%x\n", cur->tos);
found++;
}
}

View File

@ -207,15 +207,8 @@ forcejitterbuffer=no
;
;authdebug=no
;
; Finally, you can set values for your TOS bits to help improve
; performance. Valid values are:
; lowdelay -- Minimize delay
; throughput -- Maximize throughput
; reliability -- Maximize reliability
; mincost -- Minimize cost
; none -- No flags
;
tos=lowdelay
; See doc/README.tos for a description of the tos parameters.
;tos=ef
;
; If regcontext is specified, Asterisk will dynamically create and destroy
; a NoOp priority 1 extension for a given peer who registers or unregisters

View File

@ -53,10 +53,8 @@ codec=ulaw
;
flags=register,heartbeat
;
; tos is the requested type of service setting and may be one a number or
; 'lowdelay','throughput','reliability','mincost' or 'none'
;
tos=lowdelay
; See doc/README.tos for a description of this parameter.
;tos=ef
;
; Example iaxy provisioning
;

View File

@ -58,8 +58,12 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;pedantic=yes ; Enable slow, pedantic checking for Pingtel
; and multiline formatted headers for strict
; SIP compatibility (defaults to "no")
;tos=184 ; Set IP QoS to either a keyword or numeric val
;tos=lowdelay ; lowdelay,throughput,reliability,mincost,none
; See doc/README.tos for a description of these parameters.
;tos_sip=cs3 ; Sets TOS for SIP packets.
;tos_audio=ef ; Sets TOS for RTP audio packets.
;tos_video=af41 ; Sets TOS for RTP video packets.
;maxexpiry=3600 ; Max length of incoming registrations/subscriptions we allow (seconds)
;minexpiry=60 ; Minimum length of registrations/subscriptions (default 60)
;defaultexpiry=120 ; Default length of incoming/outoing registration

63
doc/ip-tos.txt Normal file
View File

@ -0,0 +1,63 @@
IP Type of Service settings for VoIP channels
---------------------------------------------
Asterisk can set the Type of Service (TOS) byte on outgoing IP packets
for various protocols. The TOS byte is used by the network to provide
some level of Quality of Service (QoS) even if the network is
congested with other traffic. For more information on Quality of
Service for VoIP networks see the "Enterprise QoS Solution Reference
Network Design Guide" version 3.3 from Cisco at:
<http://www.cisco.com/application/pdf/en/us/guest/netsol/ns432/c649/ccmigration_09186a008049b062.pdf>
In sip.conf, there are three parameters that control the TOS settings:
tos_sip, tos_audio, and tos_video. tos_sip controls what TOS SIP call
signalling packets are set to. tos_audio controls what TOS RTP audio
packets are set to. tos_video controls what TOS RTP video packets are
set to. There is a "tos" parameter that is supported for backwards
compatibility. The tos parameter should be avoided in sip.conf
because it sets all three tos settings in sip.conf to the same value.
In iax.conf, there is a tos parameter that sets the global default TOS
for IAX packets generated by chan_iax2. Since IAX connections combine
signalling, audio, and video into one UDP stream, it is not possible
to set the TOS separately for the different types of traffic.
In iaxprov.conf, there is a tos parameter that tells the IAXy what TOS
to set on packets it generates. As with the parameter in iax.conf,
IAX packets generated by an IAXy cannot have different TOS settings
based upon the type of packet. However different IAXy devices can
have different TOS settings.
The allowable values for any of the tos* parameters are:
be (best effort), cs1, af11, af12, af13, cs2, af21, af22, af23, cs3,
af31, af32, af33, cs4, af41, af42, af42, ef (expedited forwarding),
lowdelay, throughput, reliability, mincost, none
The tos* parameters also take numeric values.
The lowdelay, throughput, reliability, mincost, and none values are
deprecated because they set the IP TOS using the outdated "IP
prececence" model as defined in RFC 791 and RFC 1349.
===========================================
Configuation Parameter Recommended
File Setting
-------------------------------------------
sip.conf tos_sip cs3
sip.conf tos_audio ef
sip.conf tos_video af41
-------------------------------------------
iax.conf tos ef
-------------------------------------------
iaxprov.conf tos ef
===========================================
To get the most out of setting the TOS on packets generated by
Asterisk, you will need to ensure that your network handles packets
with a TOS properly. For Cisco devices, see the previously mentioned
"Enterprise QoS Solution Reference Network Design Guide". For Linux
systems see the "Linux Advanced Routing & Traffic Control HOWTO" at
<http://www.lartc.org/>.

View File

@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@ -38,16 +38,17 @@ extern "C" {
struct ast_ha;
extern void ast_free_ha(struct ast_ha *ha);
extern struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path);
extern int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin);
extern int ast_get_ip(struct sockaddr_in *sin, const char *value);
extern int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service);
extern int ast_ouraddrfor(struct in_addr *them, struct in_addr *us);
extern int ast_lookup_iface(char *iface, struct in_addr *address);
extern struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original);
extern int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr);
extern int ast_str2tos(const char *value, int *tos);
void ast_free_ha(struct ast_ha *ha);
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path);
int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin);
int ast_get_ip(struct sockaddr_in *sin, const char *value);
int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service);
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us);
int ast_lookup_iface(char *iface, struct in_addr *address);
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original);
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr);
int ast_str2tos(const char *value, unsigned int *tos);
const char *ast_tos2str(unsigned int tos);
#if defined(__cplusplus) || defined(c_plusplus)
}