[asterisk-dev] Re: [Fwd: [svn-commits] oej: branch oej/iaxtrunkfix-1.2 r44779

Brian Candler B.Candler at pobox.com
Wed Oct 11 04:28:27 MST 2006


On Wed, Oct 11, 2006 at 11:19:14AM +0200, Benny Amorsen wrote:
> RA> The asterisk box (with patch applied) will attempt to impact the
> RA> mtu size of the packets sent only by the asterisk box, sizing
> RA> those packets to something less then 1500 byte packets. (That will
> RA> only occur when using iax trunking only.)
> 
> But that just slows down the link at a time when throughput is
> important. Of course if the IAX packets are larger than 1500 bytes,
> that should be fixed -- path MTU discovery will help in that case.
> Also, if someone runs their DSL link at a 512 byte MTU, IAX packets
> should be sized at 512 bytes max. Again, path MTU discovery does the
> right thing.

FWIW, Linux's attempt at UDP "path MTU discovery" was pretty broken the last
time I looked at it (which was in a different context, sending L2TP frames)

Unless you explicitly set a socket option, or disable PMTU globally, then:

* All outbound UDP packets are sent with DF=1
* Therefore, UDP packets which meet a smaller MTU hop are blackholed
* You will only get a send() error if the packet is larger than the local
  interface MTU. If it is a subsequent hop then send() will be successful
  but a later router hop will discard the packet.
* You may get an ICMP message back, but it's up to your application to
  deal with it and start sending smaller UDP packets instead, using
  whatever application-level mechanisms there are for sending one message
  over multiple UDP packets.

On a FreeBSD box, UDP packets are sent with DF=0, which is sensible. You can
send large UDP packets, and if the network needs to fragment them to deliver
them, it will. (I say "sensible" because Linux disables this fragmentation,
without providing a replacement mechanism)

The following program demonstrates this - use tcpdump to look at the DF bit
of the UDP packet it sends.

-----------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    int s;
    char buf[] = "abc";
    int buflen = 3;
    struct in_addr t;
    struct sockaddr_in to;

    if ((s = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        exit(1);
    }

    to.sin_family = AF_INET;
    t.s_addr = htonl(0x01020304);
    memcpy(&to.sin_addr, &t.s_addr, 4);
    to.sin_port = htons(9999);

    sendto (s, buf, buflen, 0,
            (struct sockaddr *) &to, sizeof (to));

    return 0;
}
-----------------------------------------------------------------------

You can get DF=0 in Linux by adding the following code after the socket is
opened:

    {
        int val = IP_PMTUDISC_DONT;
        if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)) < 0)
        {
            fprintf(stderr, "Failed to disable PMTU discovery\n");
        }
    }

[This is Linux-specific code which would need to be autoconf'd out on
non-Linux systems]

Now, I don't know exactly what the "bad audio" problems are that are
described, nor do I know any details of the IAX2 protocol (SIP is enough for
me :-)

But searching the source for Asterisk, it doesn't seem to contain the string
PMTU anywhere in it, so I can only assume that you'll get the default
behaviour. This will lead to catastrophic failure if Asterisk tries to send
large UDP packets.

You can test if this is the source of the problem, by temporarily setting
/proc/sys/net/ipv4/ip_no_pmtu_disc to 1. However, I do *not* recommend this
on any production system, because it will also disable TCP path MTU
discovery (which *is* a useful and well-defined service that the kernel
provides)

If, however, this makes the audio problems go away, then a small patch to
set the IP_PMTUDISC_DONT option on the IAX2 socket will give you the benefit
of this, without affecting TCP PTMU discovery.

If you want to do UDP "path MTU discovery" in IAX2, then you'll have to
process inbound ICMP 'frag needed' messages, and you'll need to arrange so
that IAX2 sends two small packets instead of one big one when required. Care
is needed to avoid the obvious DoS if someone floods you with frag needed
messages. However you should never need to set MTU below 576, so that's your
safety net.

Sorry if this information is irrelevant to this discussion, but I just
thought my experience with UDP and DF in Linux in a different context might
at least trigger some thought process.

Regards,

Brian.


More information about the asterisk-dev mailing list