Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
devel:avps-ser [2011/10/22 21:47] 109.230.216.225 VoPGmQnhJin |
devel:avps-ser [2011/12/05 23:42] (current) 67.107.93.2 old revision restored |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | I wntaed | + | ====== AVPs in SER ====== |
+ | |||
+ | === Summary === | ||
+ | |||
+ | AVPs are divided in lists (also referred as tracks). The lists allow loading at the same time AVPs with the same name for both the caller and the callee. | ||
+ | There are 3 AVPs lists: " | ||
+ | (the list of global AVPs, loaded independent of any message attribute). If the AVP list is not specified, the " | ||
+ | |||
+ | Each AVP lists, except the global one, is further divided into levels (also referred as classes). Each level has its own namespace (several levels can contain AVPs with the same name in the same time). There are 3 AVP levels: " | ||
+ | The levels allow further grouping of the AVPs based on characteristics such as uri, user or domain and choosing the most specific defined AVP if the level is not explicitly specified (e.g. an user level AVP will override a domain level AVP with the same name). The levels can also reduce the number of attributes stored in the database, by having the attributes common for the entire domain (a kind of default " | ||
+ | If the level is no specified, SER will search for the given AVP in order, through the 3 levels. | ||
+ | |||
+ | |||
+ | === Reasons and Long Explanation === | ||
+ | |||
+ | |||
+ | (based on Jan's message from the mailing list [[http:// | ||
+ | |||
+ | A long time ago we started using AVPs to store all kinds of configuration information. We needed some sort of general configuration mechanism because real-world scripts were getting too complex and at that time the AVPs were readily available. | ||
+ | |||
+ | We started by loading attribute names and value from a database table into AVPs. This mechanism was/is same as in k. We would always load a set of attributes this way for a particular user (identified by username and domain from his/her SIP URI). With this mechanism in place, we were able to load a generic set of configuration options for a particular user of the server, | ||
+ | |||
+ | To make the AVPs easily accessible from the configuration script, we added support for AVP identifiers in the config script, so that you can access AVP with name foo as $foo. | ||
+ | |||
+ | As we migrated more and more configuration options | ||
+ | |||
+ | To get around this issue we added another list of AVPs. The new AVP list works the same way, it can contain AVPs with same names as AVPs in the original list and they do not conflict. All functions that work with lists of AVPs now take the list to work on as parameter. | ||
+ | |||
+ | To make both AVP lists available in the configuration script, we extended the syntax of AVPs identifiers so the script write can choose the AVP list to work with. SO instead of just $foo you can write either | ||
+ | |||
+ | < | ||
+ | $f.foo or $t.foo | ||
+ | </ | ||
+ | |||
+ | $f refers to the original AVP list which is commonly associated with the caller. The address/uid of the caller is taken from From header, hence the ' | ||
+ | |||
+ | The original syntax without any list identifier is still available, in other words you can still write $foo, this is defined as a shorthand for $f.foo. If you do not specify the AVP list to be used then you are referring to the list containing AVPs of the caller (From). | ||
+ | |||
+ | It also turned out that in some cases we would be having too many attributes in the database table storing AVPs. This can happen in bigger setups, having tens or hundreds of thousands users or serving multiple domains. This can slow the database down and makes SER load too much data. Based on my observations it is common that a large number of users have AVPs with same values. If ten thousands of users have attribute named ' | ||
+ | |||
+ | As a remedy | ||
+ | |||
+ | Domain-level AVPs are used to store configuration information that is shared by a group of users. Domain-level AVPs are stored in a separate database table, the name of the table is domain_attrs and its contents is cached in memory by ' | ||
+ | |||
+ | The domain-level AVPs are called ' | ||
+ | |||
+ | Again, we extended the syntax of AVP identifiers in the configuration file. So you can write: | ||
+ | |||
+ | < | ||
+ | $fu.foo -- this way you are asking for the value of the user-level foo AVP. | ||
+ | $fd.foo -- This will return the value of the domain-level foo AVP. | ||
+ | </ | ||
+ | |||
+ | And similarly there is $tu and $td for callee' | ||
+ | |||
+ | This behavior changes if you do NOT specify the level to be searched. In that case SER searches the user-level list first and if no match is found then the domain-level list will be searched. Thus if you write: | ||
+ | |||
+ | < | ||
+ | $f.foo | ||
+ | </ | ||
+ | |||
+ | then you are telling SER to search for the value of ' | ||
+ | |||
+ | Then there are the global AVPs. Global AVPs can be used to store settings applicable to the whole SIP server and all domains on that server. Global AVPs are stored in global_attrs table and the contents of that table is cached in memory by gflags module. There is only one list of global AVPs. Global AVPs can be accessed with: | ||
+ | |||
+ | < | ||
+ | $g.foo | ||
+ | </ | ||
+ | |||
+ | (note that there is no ' | ||
+ | |||
+ | < | ||
+ | $f.foo | ||
+ | </ | ||
+ | |||
+ | Then SER searches user-level AVPs first, then domain-level and then the global AVPs. | ||
+ | |||
+ | And finally there are also so called URI-level AVPs. They work just like user-level AVPs, but a single user can have multiple sets of uri-level AVPs. They are tied to SIP URIs of that user. Uri-level AVPs are denoted by ' | ||
+ | |||
+ | < | ||
+ | $fr.foo | ||
+ | </ | ||
+ | The list of URI-level AVPs is searched first, before the the list of the user-level AVPs, if the level is not explicitly specified. For example if you write: | ||
+ | |||
+ | < | ||
+ | | ||
+ | </ | ||
+ | |||
+ | Then SER searches the URI-level AVPs first, then (if not found) the user-level AVPS, then domain-level and finally the global AVPs. | ||
+ | |||
+ | |||
+ | |||
+ | === More Examples === | ||
+ | |||
+ | |||
+ | For AVPs with no list/track (f/from , t/to or g/global) and no level/class (r - URI, u - user, d - domain) specified, all the classes for URI ( r ), user (u) and domain (d) from the "from " | ||
+ | < | ||
+ | | ||
+ | </ | ||
+ | the following fully qualified AVPs will be tried (stopping at the first that exists): $fr.foo (URI-level AVP, from/caller track), | ||
+ | | ||
+ | |||
+ | For AVPs with a specified list/track (" | ||
+ | < | ||
+ | | ||
+ | </ | ||
+ | the following fully qualified AVPs will be tried: $tr.foo, $tu.foo, $td.foo, $g.foo. | ||
+ | < | ||
+ | $f.foo | ||
+ | </ | ||
+ | is equivalent with $foo ($foo is a shorthand for it). | ||
+ | |||
+ | If the track and class are specified, then only that fully qualified AVP will be tried. For example for | ||
+ | < | ||
+ | | ||
+ | </ | ||
+ | only the " | ||
+ | |||
+ | Note that the global AVP list/track does not have any levels/ | ||
+ | |||
+ | ==== Accessing AVPs via Kamailio PVs ==== | ||
+ | |||
+ | In Kamailio the AVPs are available through pseudovariable class $avp(name) - the ' | ||
+ | |||
+ | * $avp(foo) | ||
+ | * $avp(fd.foo) | ||
+ | * $avp(t.foo) |