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")
+
+ gw_socket_filter_mode (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 gw_socket_filter_mode 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")
+...
+
+
+
+
+
cluster_id (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;
}
}