Introduce support for libosmo-mgcp-client MGW pooling
Large RAN installations may benefit from distributing the RTP voice stream load over multiple media gateways. libosmo-mgcp-client supports MGW pooling since version 1.8.0 (more than one year ago). OsmoBSC has already been making use of it since then (see osmo-bsc.git 8d22e6870637ed6d392a8a77aeaebc51b23a8a50); lets use this feature in osmo-msc too. This commit is also part of a series of patches cleaning up libosmo-mgcp-client and slowly getting rid of the old non-mgw-pooled VTY configuration, in order to keep only 1 way to configure libosmo-mgcp-client through VTY. Related: SYS#5091 Related: SYS#5987 Change-Id: I7670ba56fe989706579224a364595fdd4b4708ff
This commit is contained in:
parent
f009aea963
commit
ccbd412512
|
@ -12,10 +12,11 @@ network
|
||||||
encryption a5 0
|
encryption a5 0
|
||||||
rrlp mode none
|
rrlp mode none
|
||||||
mm info 1
|
mm info 1
|
||||||
|
mgw 0
|
||||||
|
mgw remote-ip 127.0.0.1
|
||||||
|
mgw remote-port 2427
|
||||||
|
mgw local-port 2728
|
||||||
msc
|
msc
|
||||||
mgw remote-ip 127.0.0.1
|
|
||||||
mgw remote-port 2427
|
|
||||||
mgw local-port 2728
|
|
||||||
assign-tmsi
|
assign-tmsi
|
||||||
auth-tuple-max-reuse-count 3
|
auth-tuple-max-reuse-count 3
|
||||||
auth-tuple-reuse-on-error 1
|
auth-tuple-reuse-on-error 1
|
||||||
|
|
|
@ -12,6 +12,10 @@ network
|
||||||
encryption a5 0
|
encryption a5 0
|
||||||
rrlp mode none
|
rrlp mode none
|
||||||
mm info 1
|
mm info 1
|
||||||
|
mgw 0
|
||||||
|
mgw remote-ip 127.0.0.1
|
||||||
|
mgw remote-port 2427
|
||||||
|
mgw local-port 2728
|
||||||
cs7 instance 0
|
cs7 instance 0
|
||||||
point-code 0.23.1
|
point-code 0.23.1
|
||||||
asp asp-clnt-OsmoMSC-A-Iu 2905 0 m3ua
|
asp asp-clnt-OsmoMSC-A-Iu 2905 0 m3ua
|
||||||
|
@ -21,7 +25,4 @@ cs7 instance 0
|
||||||
msc
|
msc
|
||||||
cs7-instance-a 0
|
cs7-instance-a 0
|
||||||
cs7-instance-iu 0
|
cs7-instance-iu 0
|
||||||
mgw remote-ip 127.0.0.1
|
|
||||||
mgw remote-port 2427
|
|
||||||
mgw local-port 2728
|
|
||||||
assign-tmsi
|
assign-tmsi
|
||||||
|
|
|
@ -12,6 +12,10 @@ network
|
||||||
encryption a5 0
|
encryption a5 0
|
||||||
rrlp mode none
|
rrlp mode none
|
||||||
mm info 1
|
mm info 1
|
||||||
|
mgw 0
|
||||||
|
mgw remote-ip 127.0.0.1
|
||||||
|
mgw remote-port 2427
|
||||||
|
mgw local-port 2728
|
||||||
cs7 instance 0
|
cs7 instance 0
|
||||||
point-code 0.23.1
|
point-code 0.23.1
|
||||||
asp asp-clnt-OsmoMSC-A 2905 0 m3ua
|
asp asp-clnt-OsmoMSC-A 2905 0 m3ua
|
||||||
|
@ -23,7 +27,4 @@ cs7 instance 1
|
||||||
msc
|
msc
|
||||||
cs7-instance-a 0
|
cs7-instance-a 0
|
||||||
cs7-instance-iu 1
|
cs7-instance-iu 1
|
||||||
mgw remote-ip 127.0.0.1
|
|
||||||
mgw remote-port 2427
|
|
||||||
mgw local-port 2728
|
|
||||||
assign-tmsi
|
assign-tmsi
|
||||||
|
|
|
@ -149,11 +149,23 @@ default port for MGCP (2427) on local host (127.0.0.1).
|
||||||
Here is an example configuration for a remote MGW:
|
Here is an example configuration for a remote MGW:
|
||||||
|
|
||||||
----
|
----
|
||||||
msc
|
network
|
||||||
mgw remote-ip 10.9.8.7
|
mgw 0
|
||||||
mgw remote-port 2427
|
mgw remote-ip 10.9.8.7
|
||||||
mgw reset-endpoint rtpbridge/* <1>
|
mgw remote-port 2427
|
||||||
|
mgw reset-endpoint rtpbridge/* <1>
|
||||||
----
|
----
|
||||||
<1> The 'reset-endpoint' setting instructs the OsmoMGW to send a wildcarded
|
<1> The 'reset-endpoint' setting instructs the OsmoMGW to send a wildcarded
|
||||||
DLCX to the media gateway. This helps to clear lingering calls from the
|
DLCX to the media gateway. This helps to clear lingering calls from the
|
||||||
media gateway when the OsmoMSC is restarted.
|
media gateway when the OsmoMSC is restarted.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
Previous versions of OsmoMSC (1.9.0 and below) didn't have the 'mgw' VTY node and
|
||||||
|
hence didn't support the MGW pooling feature. Therefore, historically the MGW
|
||||||
|
related commands where placed under the `msc` VTY node. The MGW related commands
|
||||||
|
under the `msc` VTY are still parsed and used but its use is deprecated and
|
||||||
|
hence discouraged in favour of the new `mgw` node. Writing the config to a file
|
||||||
|
from within OsmoMSC will automatically convert the config to use the new `mgw`
|
||||||
|
node.
|
||||||
|
====
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <osmocom/crypt/utran_cipher.h>
|
#include <osmocom/crypt/utran_cipher.h>
|
||||||
|
|
||||||
#include <osmocom/mgcp_client/mgcp_client.h>
|
#include <osmocom/mgcp_client/mgcp_client.h>
|
||||||
|
#include <osmocom/mgcp_client/mgcp_client_pool.h>
|
||||||
|
|
||||||
#include <osmocom/msc/msc_common.h>
|
#include <osmocom/msc/msc_common.h>
|
||||||
#include <osmocom/msc/neighbor_ident.h>
|
#include <osmocom/msc/neighbor_ident.h>
|
||||||
|
@ -216,7 +217,9 @@ struct gsm_network {
|
||||||
struct {
|
struct {
|
||||||
struct osmo_tdef *tdefs;
|
struct osmo_tdef *tdefs;
|
||||||
struct mgcp_client_conf conf;
|
struct mgcp_client_conf conf;
|
||||||
struct mgcp_client *client;
|
/* MGW pool, also includes the single MGCP client as fallback if no
|
||||||
|
* pool is configured. */
|
||||||
|
struct mgcp_client_pool *mgw_pool;
|
||||||
} mgw;
|
} mgw;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -17,6 +17,7 @@ extern struct cmd_element cfg_no_description_cmd;
|
||||||
|
|
||||||
enum bsc_vty_node {
|
enum bsc_vty_node {
|
||||||
GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
|
GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||||
|
MGW_NODE,
|
||||||
SUBSCR_NODE,
|
SUBSCR_NODE,
|
||||||
MSC_NODE,
|
MSC_NODE,
|
||||||
MNCC_INT_NODE,
|
MNCC_INT_NODE,
|
||||||
|
|
|
@ -122,7 +122,13 @@ void call_leg_release(struct call_leg *cl)
|
||||||
|
|
||||||
static void call_leg_mgw_endpoint_gone(struct call_leg *cl)
|
static void call_leg_mgw_endpoint_gone(struct call_leg *cl)
|
||||||
{
|
{
|
||||||
|
struct mgcp_client *mgcp_client;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Put MGCP client back into MGW pool */
|
||||||
|
mgcp_client = osmo_mgcpc_ep_client(cl->mgw_endpoint);
|
||||||
|
mgcp_client_pool_put(mgcp_client);
|
||||||
|
|
||||||
cl->mgw_endpoint = NULL;
|
cl->mgw_endpoint = NULL;
|
||||||
for (i = 0; i < ARRAY_SIZE(cl->rtp); i++) {
|
for (i = 0; i < ARRAY_SIZE(cl->rtp); i++) {
|
||||||
if (!cl->rtp[i])
|
if (!cl->rtp[i])
|
||||||
|
@ -275,10 +281,17 @@ int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, uint3
|
||||||
if (cl->rtp[dir])
|
if (cl->rtp[dir])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!cl->mgw_endpoint)
|
if (!cl->mgw_endpoint) {
|
||||||
|
struct mgcp_client *mgcp_client = mgcp_client_pool_get(gsmnet->mgw.mgw_pool);
|
||||||
|
if (!mgcp_client) {
|
||||||
|
LOG_CALL_LEG(cl, LOGL_ERROR,
|
||||||
|
"cannot ensure MGW endpoint -- no MGW configured, check configuration!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
cl->mgw_endpoint = osmo_mgcpc_ep_alloc(cl->fi, CALL_LEG_EV_MGW_ENDPOINT_GONE,
|
cl->mgw_endpoint = osmo_mgcpc_ep_alloc(cl->fi, CALL_LEG_EV_MGW_ENDPOINT_GONE,
|
||||||
gsmnet->mgw.client, gsmnet->mgw.tdefs, cl->fi->id,
|
mgcp_client, gsmnet->mgw.tdefs, cl->fi->id,
|
||||||
"%s", mgcp_client_rtpbridge_wildcard(gsmnet->mgw.client));
|
"%s", mgcp_client_rtpbridge_wildcard(mgcp_client));
|
||||||
|
}
|
||||||
if (!cl->mgw_endpoint) {
|
if (!cl->mgw_endpoint) {
|
||||||
LOG_CALL_LEG(cl, LOGL_ERROR, "failed to setup MGW endpoint\n");
|
LOG_CALL_LEG(cl, LOGL_ERROR, "failed to setup MGW endpoint\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
|
@ -2033,6 +2033,8 @@ void msc_vty_init(struct gsm_network *msc_network)
|
||||||
install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
|
install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
|
||||||
install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
|
install_element(GSMNET_NODE, &cfg_net_call_wait_cmd);
|
||||||
install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
|
install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd);
|
||||||
|
mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, " ", msc_network->mgw.mgw_pool);
|
||||||
|
|
||||||
|
|
||||||
install_element(CONFIG_NODE, &cfg_msc_cmd);
|
install_element(CONFIG_NODE, &cfg_msc_cmd);
|
||||||
install_node(&msc_node, config_write_msc);
|
install_node(&msc_node, config_write_msc);
|
||||||
|
@ -2066,7 +2068,9 @@ void msc_vty_init(struct gsm_network *msc_network)
|
||||||
/* Timer configuration commands (generic osmo_tdef API) */
|
/* Timer configuration commands (generic osmo_tdef API) */
|
||||||
osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
|
osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group);
|
||||||
|
|
||||||
|
/* Deprecated: Old MGCP config without pooling support in MSC node: */
|
||||||
mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
|
mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf);
|
||||||
|
|
||||||
#ifdef BUILD_IU
|
#ifdef BUILD_IU
|
||||||
ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc);
|
ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -256,6 +256,7 @@ struct gsm_network *msc_network_alloc(void *ctx,
|
||||||
MSC_HLR_REMOTE_IP_DEFAULT);
|
MSC_HLR_REMOTE_IP_DEFAULT);
|
||||||
net->gsup_server_port = MSC_HLR_REMOTE_PORT_DEFAULT;
|
net->gsup_server_port = MSC_HLR_REMOTE_PORT_DEFAULT;
|
||||||
|
|
||||||
|
net->mgw.mgw_pool = mgcp_client_pool_alloc(net);
|
||||||
mgcp_client_conf_init(&net->mgw.conf);
|
mgcp_client_conf_init(&net->mgw.conf);
|
||||||
net->call_waiting = true;
|
net->call_waiting = true;
|
||||||
net->lcls_permitted = false;
|
net->lcls_permitted = false;
|
||||||
|
@ -546,6 +547,41 @@ extern void *tall_gsms_ctx;
|
||||||
extern void *tall_call_ctx;
|
extern void *tall_call_ctx;
|
||||||
extern void *tall_trans_ctx;
|
extern void *tall_trans_ctx;
|
||||||
|
|
||||||
|
static int msc_mgw_setup(void)
|
||||||
|
{
|
||||||
|
struct mgcp_client *mgcp_client_single;
|
||||||
|
unsigned int pool_members_initalized;
|
||||||
|
|
||||||
|
/* Initialize MGW pool. This initalizes and connects all MGCP clients that are currently configured in
|
||||||
|
* the pool. Adding additional MGCP clients to the pool is possible but the user has to configure and
|
||||||
|
* (re)connect them manually from the VTY. */
|
||||||
|
pool_members_initalized = mgcp_client_pool_connect(msc_network->mgw.mgw_pool);
|
||||||
|
if (pool_members_initalized) {
|
||||||
|
LOGP(DMSC, LOGL_NOTICE,
|
||||||
|
"MGW pool with %u pool members configured, (ignoring MGW configuration in VTY node 'msc').\n",
|
||||||
|
pool_members_initalized);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize and connect a single MGCP client. This MGCP client will appear as the one and only pool
|
||||||
|
* member if there is no MGW pool configured. */
|
||||||
|
LOGP(DMSC, LOGL_NOTICE, "No MGW pool configured, using MGW configuration in VTY node 'msc'\n");
|
||||||
|
mgcp_client_single = mgcp_client_init(msc_network, &msc_network->mgw.conf);
|
||||||
|
if (!mgcp_client_single) {
|
||||||
|
LOGP(DMSC, LOGL_ERROR, "MGW (single) client initalization failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (mgcp_client_connect(mgcp_client_single)) {
|
||||||
|
LOGP(DMSC, LOGL_ERROR, "MGW (single) connect failed at (%s:%u)\n",
|
||||||
|
msc_network->mgw.conf.remote_addr,
|
||||||
|
msc_network->mgw.conf.remote_port);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
mgcp_client_pool_register_single(msc_network->mgw.mgw_pool, mgcp_client_single);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -705,13 +741,8 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i
|
||||||
if (sms_queue_start(msc_network) != 0)
|
if (sms_queue_start(msc_network) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
msc_network->mgw.client = mgcp_client_init(
|
if (msc_mgw_setup() != 0)
|
||||||
msc_network, &msc_network->mgw.conf);
|
|
||||||
|
|
||||||
if (mgcp_client_connect(msc_network->mgw.client)) {
|
|
||||||
fprintf(stderr, "MGCPGW connect failed\n");
|
|
||||||
return 7;
|
return 7;
|
||||||
}
|
|
||||||
|
|
||||||
if (ss7_setup(tall_msc_ctx, &sccp_a, &sccp_iu)) {
|
if (ss7_setup(tall_msc_ctx, &sccp_a, &sccp_iu)) {
|
||||||
fprintf(stderr, "Setting up SCCP client failed.\n");
|
fprintf(stderr, "Setting up SCCP client failed.\n");
|
||||||
|
|
|
@ -1136,6 +1136,7 @@ static void run_tests(int nr)
|
||||||
struct gsm_network *test_net(void *ctx)
|
struct gsm_network *test_net(void *ctx)
|
||||||
{
|
{
|
||||||
struct gsm_network *net = gsm_network_init(ctx, mncc_recv);
|
struct gsm_network *net = gsm_network_init(ctx, mncc_recv);
|
||||||
|
struct mgcp_client *client;
|
||||||
|
|
||||||
net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
|
net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
|
||||||
net->gsup_server_port = 0;
|
net->gsup_server_port = 0;
|
||||||
|
@ -1172,8 +1173,9 @@ struct gsm_network *test_net(void *ctx)
|
||||||
net->mgw.tdefs = g_mgw_tdefs;
|
net->mgw.tdefs = g_mgw_tdefs;
|
||||||
mgcp_client_conf_init(&net->mgw.conf);
|
mgcp_client_conf_init(&net->mgw.conf);
|
||||||
net->mgw.tdefs = g_mgw_tdefs;
|
net->mgw.tdefs = g_mgw_tdefs;
|
||||||
net->mgw.client = mgcp_client_init(net, &net->mgw.conf);
|
net->mgw.mgw_pool = mgcp_client_pool_alloc(net);
|
||||||
|
client = mgcp_client_init(net, &net->mgw.conf);
|
||||||
|
mgcp_client_pool_register_single(net->mgw.mgw_pool, client);
|
||||||
return net;
|
return net;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ OsmoMSC(config-net)# list
|
||||||
no timezone
|
no timezone
|
||||||
call-waiting
|
call-waiting
|
||||||
no call-waiting
|
no call-waiting
|
||||||
|
mgw <0-255>
|
||||||
|
no mgw <0-255>
|
||||||
|
|
||||||
OsmoMSC(config-net)# encryption?
|
OsmoMSC(config-net)# encryption?
|
||||||
encryption Encryption options
|
encryption Encryption options
|
||||||
|
@ -152,6 +154,10 @@ network
|
||||||
authentication optional
|
authentication optional
|
||||||
rrlp mode none
|
rrlp mode none
|
||||||
mm info 1
|
mm info 1
|
||||||
|
mgw 0
|
||||||
|
mgw local-port 2728
|
||||||
|
mgw remote-ip 127.0.0.1
|
||||||
|
mgw remote-port 2427
|
||||||
msc
|
msc
|
||||||
mncc guard-timeout 180
|
mncc guard-timeout 180
|
||||||
ncss guard-timeout 30
|
ncss guard-timeout 30
|
||||||
|
@ -160,9 +166,6 @@ msc
|
||||||
...
|
...
|
||||||
auth-tuple-max-reuse-count 3
|
auth-tuple-max-reuse-count 3
|
||||||
auth-tuple-reuse-on-error 1
|
auth-tuple-reuse-on-error 1
|
||||||
mgw local-port 2728
|
|
||||||
mgw remote-ip 127.0.0.1
|
|
||||||
mgw remote-port 2427
|
|
||||||
mncc-int
|
mncc-int
|
||||||
default-codec tch-f fr
|
default-codec tch-f fr
|
||||||
default-codec tch-h hr
|
default-codec tch-h hr
|
||||||
|
|
Loading…
Reference in New Issue