diff --git a/src/modules/lcr/doc/lcr_admin.xml b/src/modules/lcr/doc/lcr_admin.xml index be2c8bbac55..e0e8755322f 100644 --- a/src/modules/lcr/doc/lcr_admin.xml +++ b/src/modules/lcr/doc/lcr_admin.xml @@ -127,7 +127,8 @@ As a side effect of gateway selection, selected gateway's tag and flags (that may contain information about the gateway and its capabilities) are stored to tag_avp and flags_avp, respectively, if the corresponding - module parameter has been defined. + module parameter has been defined. In the same way, rule_id_avp, if defined, + contains the id of the rule that selected the gateway. @@ -867,6 +868,28 @@ modparam("lcr", "flags_avp", "$avp(i:712)") +
+ <varname>rule_id_avp</varname> (AVP string) + + If defined, an AVP where successful next_gw and from_gw + functions store matching rule's id. + + + + There is NO default value, i.e, if not defined, + matching rule's id is not stored anywhere. + + + + Setting <varname>rule_id_avp</varname> module parameter + + ... + modparam("lcr", "rule_id_avp", "$avp(i:712)") + ... + + +
+
<varname>mt_pv_values</varname> (AVP string) @@ -1302,7 +1325,8 @@ if (!load_gws(1, $rU, $var(caller_uri))) { As a side effect, stores gateway's tag and flags to tag_avp and flags_avp, respectively, if the corresponding - module parameter has been defined. + module parameter has been defined. In the same way, rule_id_avp, + if defined, contains the id of the rule that selected the gateway. Returns 1 on success and -1 if there were no gateways @@ -1425,7 +1449,8 @@ defunct_gw(60); If request comes from a gateway, gateway's tag and flags are stored as a side effect to tag_avp and flags_avp, respectively, if the corresponding - module parameter has been defined. + module parameter has been defined. In the same way, rule_id_avp, + if defined, contains the id of the rule that selected the gateway. Returns 1 on success and -1 on failure or on error. @@ -1475,7 +1500,8 @@ if (from_gw(1, $avp(s:real_source_addr), 2) { If request comes from a gateway, gateway's tag and flags are stored as a side effect to tag_avp and flags_avp, respectively, if the corresponding - module parameter has been defined. + module parameter has been defined. In the same way, rule_id_avp, + if defined, contains the id of the rule that selected the gateway. Execution time of from_gw() function is M * O(log N), diff --git a/src/modules/lcr/lcr_mod.c b/src/modules/lcr/lcr_mod.c index d09ea0b3ed4..5e400ddd79d 100644 --- a/src/modules/lcr/lcr_mod.c +++ b/src/modules/lcr/lcr_mod.c @@ -172,6 +172,7 @@ static char *gw_uri_avp_param = NULL; static char *ruri_user_avp_param = NULL; static char *tag_avp_param = NULL; static char *flags_avp_param = NULL; +static char *rule_id_avp_param = NULL; static char *defunct_gw_avp_param = NULL; static char *lcr_id_avp_param = NULL; static char *mt_pv_values_param = NULL; @@ -216,6 +217,8 @@ static int tag_avp_type; static int_str tag_avp; static int flags_avp_type; static int_str flags_avp; +static int rule_id_avp_type; +static int_str rule_id_avp; static int defunct_gw_avp_type; static int_str defunct_gw_avp; static int lcr_id_avp_type; @@ -331,6 +334,7 @@ static param_export_t params[] = { {"ruri_user_avp", PARAM_STRING, &ruri_user_avp_param}, {"tag_avp", PARAM_STRING, &tag_avp_param}, {"flags_avp", PARAM_STRING, &flags_avp_param}, + {"rule_id_avp", PARAM_STRING, &rule_id_avp_param}, {"defunct_capability", INT_PARAM, &defunct_capability_param}, {"defunct_gw_avp", PARAM_STRING, &defunct_gw_avp_param}, {"lcr_id_avp", PARAM_STRING, &lcr_id_avp_param}, @@ -539,6 +543,21 @@ static int mod_init(void) flags_avp_type = avp_flags; } + if(rule_id_avp_param) { + s.s = rule_id_avp_param; + s.len = strlen(s.s); + avp_spec = pv_cache_get(&s); + if(avp_spec == NULL || (avp_spec->type != PVT_AVP)) { + LM_ERR("malformed or non AVP definition <%s>\n", rule_id_avp_param); + return -1; + } + if(pv_get_avp_name(0, &(avp_spec->pvp), &rule_id_avp, &avp_flags) != 0) { + LM_ERR("invalid AVP definition <%s>\n", rule_id_avp_param); + return -1; + } + rule_id_avp_type = avp_flags; + } + if((ping_interval_param != 0) && (ping_interval_param < 10)) { LM_ERR("invalid ping_interval value '%u'\n", ping_interval_param); return -1; @@ -1805,7 +1824,8 @@ static inline int encode_avp_value(char *value, unsigned int gw_index, unsigned int prefix_len, char *tag, unsigned int tag_len, struct ip_addr *ip_addr, char *hostname, unsigned int hostname_len, unsigned int port, char *params, unsigned int params_len, - char *transport, unsigned int transport_len, unsigned int flags) + char *transport, unsigned int transport_len, unsigned int flags, + unsigned int rule_id) { char *at, *string; int len; @@ -1857,13 +1877,17 @@ static inline int encode_avp_value(char *value, unsigned int gw_index, /* flags */ string = int2str(flags, &len); append_str(at, string, len); + append_chr(at, '|'); + /* rule id */ + string = int2str(rule_id, &len); + append_str(at, string, len); return at - value; } static inline int decode_avp_value(char *value, unsigned int *gw_index, str *scheme, unsigned int *strip, str *prefix, str *tag, struct ip_addr *addr, str *hostname, str *port, str *params, - str *transport, unsigned int *flags) + str *transport, unsigned int *flags, unsigned int *rule_id) { unsigned int u; str s; @@ -1970,6 +1994,15 @@ static inline int decode_avp_value(char *value, unsigned int *gw_index, s.s = sep + 1; s.len = strlen(s.s); str2int(&s, flags); + sep = index(s.s, '|'); + if(sep == NULL) { + LM_ERR("flags was not found in AVP value\n"); + return 0; + } + /* rule_id */ + s.s = sep + 1; + s.len = strlen(s.s); + str2int(&s, rule_id); return 1; } @@ -1979,7 +2012,7 @@ static inline int decode_avp_value(char *value, unsigned int *gw_index, void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws, unsigned int gw_cnt, str *ruri_user) { - unsigned int i, index, strip, hostname_len, params_len; + unsigned int i, index, strip, hostname_len, params_len, rule_id; int prefix_len, tag_len; str value; char encoded_value[MAX_URI_LEN]; @@ -1992,6 +2025,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws, if(matched_gws[i].duplicate == 1) continue; index = matched_gws[i].gw_index; + rule_id = matched_gws[i].rule_id; hostname_len = gws[index].hostname_len; params_len = gws[index].params_len; strip = gws[index].strip; @@ -2009,6 +2043,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws, + 6 /* port */ + params_len /* params */ + 15 /* transport */ + 10 /* flags */ + 7 /* separators */ + + 10 /* rule_id */ > MAX_URI_LEN) { LM_ERR("too long AVP value\n"); goto skip; @@ -2018,7 +2053,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws, gws[index].tag, tag_len, &gws[index].ip_addr, gws[index].hostname, hostname_len, gws[index].port, gws[index].params, params_len, gws[index].transport, - gws[index].transport_len, gws[index].flags); + gws[index].transport_len, gws[index].flags, rule_id); value.s = (char *)&(encoded_value[0]); val.s = value; add_avp(gw_uri_avp_type | AVP_VAL_STR, gw_uri_avp, val); @@ -2137,6 +2172,7 @@ int load_gws_dummy(int lcr_id, str *ruri_user, str *from_uri, str *request_uri, || (gws[t->gw_index].state == GW_INACTIVE)) goto skip_gw; matched_gws[gw_index].gw_index = t->gw_index; + matched_gws[gw_index].rule_id = rule->rule_id; matched_gws[gw_index].prefix_len = pl->prefix_len; matched_gws[gw_index].priority = t->priority; matched_gws[gw_index].weight = t->weight * (kam_rand() >> 8); @@ -2301,6 +2337,7 @@ static int ki_load_gws_furi( || (gws[t->gw_index].state == GW_INACTIVE)) goto skip_gw; matched_gws[gw_index].gw_index = t->gw_index; + matched_gws[gw_index].rule_id = rule->rule_id; matched_gws[gw_index].prefix_len = pl->prefix_len; matched_gws[gw_index].priority = t->priority; matched_gws[gw_index].weight = t->weight * (kam_rand() >> 8); @@ -2436,7 +2473,7 @@ static int load_gws(struct sip_msg *_m, int argc, action_u_t argv[]) static int generate_uris(struct sip_msg *_m, char *r_uri, str *r_uri_user, unsigned int *r_uri_len, char *dst_uri, unsigned int *dst_uri_len, struct ip_addr *addr, unsigned int *gw_index, unsigned int *flags, - str *tag) + str *tag, unsigned int *rule_id) { int_str gw_uri_val; struct usr_avp *gu_avp; @@ -2450,7 +2487,7 @@ static int generate_uris(struct sip_msg *_m, char *r_uri, str *r_uri_user, return 0; /* No more gateways left */ decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix, - &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags); + &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags, rule_id); if(addr->af != 0) { addr_str.s = ip_addr2a(addr); @@ -2808,7 +2845,7 @@ static int ki_next_gw(sip_msg_t *_m) int rval; str uri_str, tag_str; char tag[MAX_TAG_LEN]; - unsigned int flags, r_uri_len, dst_uri_len, gw_index; + unsigned int flags, r_uri_len, dst_uri_len, gw_index, rule_id; char r_uri[MAX_URI_LEN], dst_uri[MAX_URI_LEN]; struct ip_addr addr; @@ -2828,7 +2865,7 @@ static int ki_next_gw(sip_msg_t *_m) return -1; } if(generate_uris(_m, r_uri, &(_m->parsed_uri.user), &r_uri_len, dst_uri, - &dst_uri_len, &addr, &gw_index, &flags, &tag_str) + &dst_uri_len, &addr, &gw_index, &flags, &tag_str, &rule_id) <= 0) { return -1; } @@ -2847,7 +2884,7 @@ static int ki_next_gw(sip_msg_t *_m) * and Destination URIs. */ if(generate_uris(_m, r_uri, &(ruri_user_val.s), &r_uri_len, dst_uri, - &dst_uri_len, &addr, &gw_index, &flags, &tag_str) + &dst_uri_len, &addr, &gw_index, &flags, &tag_str, &rule_id) <= 0) { return -1; } @@ -2887,6 +2924,13 @@ static int ki_next_gw(sip_msg_t *_m) LM_DBG("added tag_avp <%.*s>\n", val.s.len, val.s.s); } + /* Set rule_id_avp */ + if(rule_id_avp_param) { + val.n = rule_id; + add_avp(rule_id_avp_type, rule_id_avp, val); + LM_DBG("added rule_id_avp <%u>\n", (unsigned int)val.n); + } + /* Add index of selected gw to defunct gw AVP */ if((defunct_capability_param > 0) || (ping_interval_param > 0)) { delete_avp(defunct_gw_avp_type, defunct_gw_avp); diff --git a/src/modules/lcr/lcr_mod.h b/src/modules/lcr/lcr_mod.h index 7dd6f4fcdb5..3bcf495e335 100644 --- a/src/modules/lcr/lcr_mod.h +++ b/src/modules/lcr/lcr_mod.h @@ -80,6 +80,7 @@ struct rule_id_info struct matched_gw_info { unsigned short gw_index; + unsigned int rule_id; unsigned short prefix_len; unsigned short priority; unsigned int weight;