[asterisk-dev] chan_iax2 improvements (was chan_sip -- improving the speed of sip reloads)

Russell Bryant russell at digium.com
Thu Nov 22 11:25:25 CST 2007

Steve Murphy wrote:
> One of the fun things about hash tables is that you don't need to
> actually store the key in the structure, as long as you can **derive**
> it from the other members of the object. For instance, if you have an
> object with an ip and port, and you want to use those as a key, you set
> up your hash functions like this:
> compare_func:
>   if (objA.ip == objB.ip && objA.port == objB.port) ...
> hash_func:
>   return (int)obj.ip + (int)obj.port;

I have had this thought, but haven't been able to pull it off yet.  I tried once
before to create a second container for the IAX2 pvt struct that was a hash
table keyed on the peer's IP/port/call number, but it was crashing a lot, so I
ripped it back out.  Of course, all of my hash table management was hacked
directly into chan_iax2.  Now that we have these new APIs for managing hash
tables, then I think it's time to try again.  :)

> I'd offer to help you do it over the thanksgiving vacation, but I get
> this feeling like you're probably half-way thru it right now
> anyway... ;)

Ha!  No, I actually haven't started.  I'll create a branch if I start working on
it, but I doubt it will be soon.  However, I think it would be a great project
for you (Steve) to take on after you finish your work on data structure
management improvements in chan_sip.  I can certainly work with you on it, as well.

For the sake of having it documented, I will go ahead and describe how I think
it could be done.

(A little bit of IAX2 clarification ... in IAX2, every call has two call numbers
associated with it.  Each endpoint assigns a unique call number to the call.
So, I will refer to them as the local call number for the number we assign, and
the remote call number for the number that the other end of the call assigns.)

The container for IAX2 pvt structs right now is an array.  The index of the
array is the local call number.  So, for an incoming frame, if we can grab the
local call number from it, we have the index into the array for the pvt struct.
 However, media frames only carry the source call number.  So, for an incoming
media frame, that is the remote call number, which leaves us no way to find the
matching pvt except to iterate through every single one.

So, we need another way to index pvt structures that is based on information
about the remote endpoint.  My plan of attack is this:

1) Create a hash table as a second container for the iax2_pvt struct.

   - For the hash function, return some value that takes into account the peer
     IP, port number, and call number.  When I did this before, I used the
     following code to generate a 16 bit hash value, but there may be another
     method that provides better distribution.

      return ( (sin->sin_addr.s_addr >> 16) ^ sin->sin_addr.s_addr ^
                sin->sin_port ^ callno ) % PVT_HASH_SIZE;

   - For the compare function, the unique match is the remote IP/port/callnum.
     This is basically just using the existing match() function that
     find_callno() uses today.

2) Put pvt's in the hash table as soon as the remote call number is known, and
re-insert it at any point the remote call number changes.  This part is actually
pretty easy, it is just any part of the code that sets the "peercallno"
variable.  There are just a few of them.

3) Modify the find_callno() function to first attempt to look up the pvt struct
in the hash table.  If it is not there (because the peer call number is not yet
known), then revert back to iterating through.

    - However, I definitely would like to figure out _exactly_ what situations
      find_callno would be called and the pvt isn't found in the hash table.  I
      am thinking that we can come up with a better method of accounting for
      whatever the use may be.  I think one of the uses is to find unused call

4) In iax2_destroy(), remove the pvt from the hash table if it is in there
before destroying the object.

Russell Bryant
Senior Software Engineer
Open Source Team Lead
Digium, Inc.

More information about the asterisk-dev mailing list