[asterisk-dev] Problems with RTCP

John Todd jtodd at digium.com
Thu Nov 6 11:44:29 CST 2008

On Nov 6, 2008, at 7:31 AM, Johansson Olle E wrote:

> 6 nov 2008 kl. 16.15 skrev Atis Lezdins:
>> I wonder would it be possible to append RTCP responses to CDR, as  
>> Dial
>> is producing separate CDRs for each channel involved. So each channel
>> could have their own RTCP stats.
> That was my original proposal, alongside with the channel variables.
> Only channel
> variables got a response. Well, much have happened since then and we
> now have
> many CDR drivers with CDR variable support, so we could easily pop it
> into
> a new field, like RTPQOS-audio-in, RTPQOS-audio-out. The problem as
> always is
> that so much can happen during the call, the out-channel can become an
> in-channel.
> Someone that knows more about CDRs propably needs to figure out how to
> handle that.
> Anyway, I like putting them in CDRs. Or in a separate table. We could
> propably use
> realtime for that, so if you've enabled realtime with connection name
> we would save SIP call ID and the RTP stats for audio and video in the
> database.
> That might be easier to accomplish, then you have to store the SIP
> call ID in the
> CDR fields in the dialplan and you can match later on.
> Just brainstorming - any other ideas out there?
> /O

While I think it seems natural to add them to the CDR events, I don't  
think it is the appropriate place because of the problems you mention  
- RTP paths aren't static.  It is possible to have a call with two or  
three media streams.  If there was a single CQDR record, how would it  
be computed?  Do we add all these up?  Ugh.  Many calls also have  
multiple destination IP addresses involved for the RTP streams - how  
do we say what this quality information references as far as an  

Keeping these records straight is also somewhat difficult, as there  
often are two legs associated with a call (inbound to *, and then  
Dial() outbound) but that is left as an exercise to the implementer to  
ensure that they capture the correct data for the correct leg.  It  
seems that it would be much easier if $CHANNEL could take a channel  
name as an additional qualifier instead of just using the current  


Plus, there's a lot of data in QOS statistics.  Do we want that  
cluttering the CDR tables?  I don't believe so.  Below is a quick  
dialplan that shows all the things that might be relevant in a CDR  
record - it's quite a pile.  Plus, in my various tests, many (but not  
all) of these values remained steadfastly at "0" or are wildly  
incorrect despite RTCP-capable endpoints, so I am concerned that the  
current code doesn't do quite what it should (though it is of course  
possible that my RTCP endponts (Cisco, Eyebeam) are also wrong.)

My idea: It seems that there needs to be a table specifically for  
keeping data involving RTP streams, and due to the monolithic nature  
of Dial() it may even be easier just to keep those records directly  
from the RTP code instead of trying to bubble it up to the dialplan.   
Each new RTP stream would create a new CQDR record, regardless of what  
the user experience or dialplan path was.  If you could set a key  
value in the dialplan (something like "CQDRKEY" or something like  
that) which would then allow post-call correlation, or you could just  
use the channel name as the key.

It could use the same methods that we have right now for CDR storage -  
ODBC, CSV, whatever.  Just re-use all that code but with a different  
config file.  We're now on year 4 of this discussion - who  
volunteers?  :-)

Anyway, here's my ugly dialplan that can show you how unusual the RTCP  
data (or regular RTP data) can get.  Try it with your client and see  
what happens.  I also enclose a sample output from a connection  
between SVN-TRUNK as of this morning with Eyebeam for Mac  
release 1100v build 47069.

exten => 999,1,Answer()
exten => 999,n,Playback(tt-monkeys)
exten => 999,n,Log(DEBUG,local_ssrc:           $ 
exten => 999,n,Log(DEBUG,local_lostpackets:    $ 
exten => 999,n,Log(DEBUG,local_jitter:         $ 
exten => 999,n,Log(DEBUG,local_maxjitter:      $ 
exten => 999,n,Log(DEBUG,local_minjitter:      $ 
exten => 999,n,Log(DEBUG,local_normdevjitter:  $ 
exten => 999,n,Log(DEBUG,local_stdevjitter:    $ 
exten => 999,n,Log(DEBUG,local_count:          $ 
exten => 999,n,Log(DEBUG,remote_ssrc:          $ 
exten => 999,n,Log(DEBUG,remote_lostpackets:   $ 
exten => 999,n,Log(DEBUG,remote_jitter:        $ 
exten => 999,n,Log(DEBUG,remote_maxjitter:     $ 
exten => 999,n,Log(DEBUG,remote_minjitter:     $ 
exten => 999,n,Log(DEBUG,remote_normdevjitter: $ 
exten => 999,n,Log(DEBUG,remote_stdevjitte:    $ 
exten => 999,n,Log(DEBUG,remote_count:         $ 
exten => 999,n,Log(DEBUG,maxrtt:               $ 
exten => 999,n,Log(DEBUG,minrtt:               $ 
exten => 999,n,Log(DEBUG,normdevrtt:           $ 
exten => 999,n,Log(DEBUG,stdevrtt:             $ 
exten => 999,n,Log(DEBUG,rtpdest:              $ 
exten => 999,n,Hangup

Sample output:

     -- Executing [999 at default-context:3] Log("SIP/2204-8063d014",  
"DEBUG,local_ssrc:           499616254") in new stack
     -- Executing [999 at default-context:4] Log("SIP/2204-8063d014",  
"DEBUG,local_lostpackets:    0") in new stack
     -- Executing [999 at default-context:5] Log("SIP/2204-8063d014",  
"DEBUG,local_jitter:         5") in new stack
     -- Executing [999 at default-context:6] Log("SIP/2204-8063d014",  
"DEBUG,local_maxjitter:      6") in new stack
     -- Executing [999 at default-context:7] Log("SIP/2204-8063d014",  
"DEBUG,local_minjitter:      0") in new stack
     -- Executing [999 at default-context:8] Log("SIP/2204-8063d014",  
"DEBUG,local_normdevjitter:  5") in new stack
     -- Executing [999 at default-context:9] Log("SIP/2204-8063d014",  
"DEBUG,local_stdevjitter:    Inf") in new stack
     -- Executing [999 at default-context:10] Log("SIP/2204-8063d014",  
"DEBUG,local_count:          807") in new stack
     -- Executing [999 at default-context:11] Log("SIP/2204-8063d014",  
"DEBUG,remote_ssrc:          3944626440") in new stack
     -- Executing [999 at default-context:12] Log("SIP/2204-8063d014",  
"DEBUG,remote_lostpackets:   0") in new stack
     -- Executing [999 at default-context:13] Log("SIP/2204-8063d014",  
"DEBUG,remote_jitter:        0") in new stack
     -- Executing [999 at default-context:14] Log("SIP/2204-8063d014",  
"DEBUG,remote_maxjitter:     1177961526000") in new stack
     -- Executing [999 at default-context:15] Log("SIP/2204-8063d014",  
"DEBUG,remote_minjitter:     0") in new stack
     -- Executing [999 at default-context:16] Log("SIP/2204-8063d014",  
"DEBUG,remote_normdevjitter: 235592311400") in new stack
     -- Executing [999 at default-context:17] Log("SIP/2204-8063d014",  
"DEBUG,remote_stdevjitte:    7509313529832") in new stack
     -- Executing [999 at default-context:18] Log("SIP/2204-8063d014",  
"DEBUG,remote_count:         808") in new stack
     -- Executing [999 at default-context:19] Log("SIP/2204-8063d014",  
"DEBUG,maxrtt:               15636177") in new stack
     -- Executing [999 at default-context:20] Log("SIP/2204-8063d014",  
"DEBUG,minrtt:               0") in new stack
     -- Executing [999 at default-context:21] Log("SIP/2204-8063d014",  
"DEBUG,normdevrtt:           3909044") in new stack
     -- Executing [999 at default-context:22] Log("SIP/2204-8063d014",  
"DEBUG,stdevrtt:             49826473") in new stack
     -- Executing [999 at default-context:23] Log("SIP/2204-8063d014",  
"DEBUG,rtpdest:    ") in new stack
     -- Executing [999 at default-context:24] Hangup("SIP/2204-8063d014",  
"") in new stack


John Todd
jtodd at digium.com        +1-256-428-6083
Asterisk Open Source Community Director

More information about the asterisk-dev mailing list