diff --git a/modules/drouting/doc/drouting_admin.xml b/modules/drouting/doc/drouting_admin.xml index 60da877b0f1..184a3fa2a6f 100644 --- a/modules/drouting/doc/drouting_admin.xml +++ b/modules/drouting/doc/drouting_admin.xml @@ -925,6 +925,65 @@ modparam("drouting", "probing_socket", "udp:192.168.1.100:5060") +
+ <varname>gw_socket_filter_mode</varname> (string) + + This parameter controls the gateway filtering during DB loading, or which + gateways are loaded or not into memory depending on the configured + socket they have. + + + The supported filtering modes are: + + + + + "all" - all the gateways + defined in DB are loaded into memory, disregarding what socket + value they have. NOTE: for the gw sockets not matching any OpenSIPS + listeners/sockets, the GW will be loaded with NULL/no socket. + + + + + "ignore" - all the gateways + defined in DB are loaded into memory, but ignoring the socket + value they have (the socket will be set to NULL/NONE with no + attempt to check it against the OpenSIPS listeners/sockets). + + + + + "matched-only" - in this mode + the module will load from DB only the gateways that have a + configured a socket matching any of the the OpenSIPS + listeners/sockets. If the gateways socket does not match, it will + be discards, not loaded into memory at all. + + + + + + Default value is "all". + + + + Set <varname>gw_socket_filter_mode</varname> parameter + +... +# multiple OpenSIPS instances sharing a DR setting, so each should +# load only the GWs they have sockets for. +modparam("drouting", "gw_socket_filter_mode", "matched-only") +... +# an OpenSIPs instance not doing routing, but needing to be +# aware of all the gws, so load them all ignoring the sockets +modparam("drouting", "gw_socket_filter_mode", "ignore") +... + + +
+ +
<varname>cluster_id</varname> (integer) diff --git a/modules/drouting/dr_load.c b/modules/drouting/dr_load.c index 4f399715bf5..c9443107711 100644 --- a/modules/drouting/dr_load.c +++ b/modules/drouting/dr_load.c @@ -42,6 +42,15 @@ #include "dr_db_def.h" +enum dr_gw_socket_filter_mode { + DR_GW_SOCK_FILTER_MODE_NONE=0, + DR_GW_SOCK_FILTER_MODE_IGNORE, + DR_GW_SOCK_FILTER_MODE_MATCH +}; + +enum dr_gw_socket_filter_mode gw_sock_filter = DR_GW_SOCK_FILTER_MODE_NONE; + + #define check_val2( _col, _val, _type1, _type2, _not_null, _is_empty_str) \ do{\ if ((_val)->type!=(_type1) && (_val)->type!=(_type2)) { \ @@ -77,6 +86,23 @@ }while(0) +int dr_set_gw_sock_filter_mode(char *mode) +{ + if ( strcasecmp( mode, "none")==0 ) { + gw_sock_filter = DR_GW_SOCK_FILTER_MODE_NONE; + return 0; + } + if ( strcasecmp( mode, "ignore")==0 ) { + gw_sock_filter = DR_GW_SOCK_FILTER_MODE_IGNORE; + return 0; + } + if ( strcasecmp( mode, "matched-only")==0 ) { + gw_sock_filter = DR_GW_SOCK_FILTER_MODE_MATCH; + return 0; + } + return -1; +} + static int add_rule(rt_data_t *rdata, char *grplst, str *prefix, rt_info_t *rule, osips_malloc_f malloc_f, osips_free_f free_f) { @@ -369,7 +395,8 @@ rt_data_t* dr_load_routing_info(struct head_db *part, int_vals[INT_VALS_PROBE_DRD_COL] = VAL_INT(ROW_VALUES(row)+7); /* SOCKET column */ check_val( sock_drd_col, ROW_VALUES(row)+8, DB_STRING, 0, 0); - if ( !VAL_NULL(ROW_VALUES(row)+8) && + if ( gw_sock_filter!=DR_GW_SOCK_FILTER_MODE_IGNORE && + !VAL_NULL(ROW_VALUES(row)+8) && (s_sock.s=(char*)VAL_STRING(ROW_VALUES(row)+8))[0]!=0 ) { s_sock.len = strlen(s_sock.s); if (parse_phostport( s_sock.s, s_sock.len, &host.s, &host.len, @@ -382,6 +409,8 @@ rt_data_t* dr_load_routing_info(struct head_db *part, } else { sock = grep_internal_sock_info( &host, port, proto); if (sock == NULL) { + if (gw_sock_filter==DR_GW_SOCK_FILTER_MODE_MATCH) + continue; LM_ERR("GW <%s>(%s): socket <%.*s> is not local to " "OpenSIPS (we must listen on it) -> ignoring socket\n", str_vals[STR_VALS_GWID_DRD_COL], diff --git a/modules/drouting/dr_load.h b/modules/drouting/dr_load.h index 843fbaac3b3..00acffb666d 100644 --- a/modules/drouting/dr_load.h +++ b/modules/drouting/dr_load.h @@ -28,8 +28,11 @@ #include "dr_partitions.h" #include "routing.h" +int dr_set_gw_sock_filter_mode(char *mode); + void dr_update_head_cache(struct head_db *head); + rt_data_t* dr_load_routing_info(struct head_db *current_partition, - int persistent_state, str *rules_tables, int rules_no); + int persistent_state, str *rules_tables, int rules_no); #endif diff --git a/modules/drouting/drouting.c b/modules/drouting/drouting.c index 6f57cb5e292..2cd1161539b 100644 --- a/modules/drouting/drouting.c +++ b/modules/drouting/drouting.c @@ -136,6 +136,8 @@ pv_spec_t partition_spec; int dr_rpm_enable = 0; struct head_cache *dr_cache; +static char *gw_sock_filter_s = NULL; + /* * global pointers for faster parameter passing between functions * meaning: current script pvar to dump attrs in (NULL to ignore) @@ -499,6 +501,7 @@ static param_export_t params[] = { {"cluster_probing_mode",STR_PARAM, &dr_cluster_prob_mode_s}, {"enable_restart_persistency",INT_PARAM, &dr_rpm_enable }, {"extra_prefix_chars", STR_PARAM, &extra_prefix_chars }, + {"gw_socket_filter_mode", STR_PARAM, &gw_sock_filter_s }, {0, 0, 0} }; @@ -2015,6 +2018,14 @@ static int dr_init(void) goto error; } + if (gw_sock_filter_s) { + if (dr_set_gw_sock_filter_mode(gw_sock_filter_s)<0) { + LM_ERR("failed to set the GW socket filtering, unknown \"%s\"" + "mode\n", gw_sock_filter_s); + goto error; + } + } + return 0; error_cfg: @@ -3724,6 +3735,7 @@ static int route2_gw(struct sip_msg* msg, str* ids, pv_spec_t* gw_attr, pcr_t *pcr = NULL; map_iterator_t cr_it; void** dest; + int_str val; if(part== NULL) { LM_ERR("Partition is mandatory for route_to_gw.\n"); @@ -3824,6 +3836,18 @@ static int route2_gw(struct sip_msg* msg, str* ids, pv_spec_t* gw_attr, 0, &pv_val) != 0) LM_ERR("failed to set value for " "CARRIER attrs pvar\n"); + /* insert the carrier ID also */ + if (current_partition->carrier_id_avp!=-1) { + val.s = pcr->id; + /* we need to replace as the + * push_gw_for_usage() function + * already added an empty one + */ + if (replace_avp( AVP_VAL_STR, + current_partition->carrier_id_avp, + val, 0)!=0) + LM_ERR("failed to update carrier ID avp\n"); + } goto cr_end; } }