Introduce support for libosmo-mgcp-client MGW pooling

Change-Id: I7670ba56fe989706579224a364595fdd4b4708ff
This commit is contained in:
Pau Espin 2022-10-17 18:09:15 +02:00
parent e4f429cc90
commit b332e84eca
6 changed files with 61 additions and 12 deletions

View File

@ -16,6 +16,7 @@
#include <osmocom/crypt/utran_cipher.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/neighbor_ident.h>
@ -216,7 +217,9 @@ struct gsm_network {
struct {
struct osmo_tdef *tdefs;
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;
struct {

View File

@ -25,6 +25,7 @@ enum bsc_vty_node {
HLR_NODE,
CFG_SGS_NODE,
SMSC_NODE,
MGW_NODE,
};
int bsc_vty_init_extra(void);

View File

@ -17,6 +17,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <asm-generic/errno-base.h>
#include <osmocom/core/fsm.h>
#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
@ -275,10 +276,17 @@ int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, uint3
if (cl->rtp[dir])
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,
gsmnet->mgw.client, gsmnet->mgw.tdefs, cl->fi->id,
"%s", mgcp_client_rtpbridge_wildcard(gsmnet->mgw.client));
mgcp_client, gsmnet->mgw.tdefs, cl->fi->id,
"%s", mgcp_client_rtpbridge_wildcard(mgcp_client));
}
if (!cl->mgw_endpoint) {
LOG_CALL_LEG(cl, LOGL_ERROR, "failed to setup MGW endpoint\n");
return -EIO;

View File

@ -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_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_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) */
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);
#ifdef BUILD_IU
ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc);
#endif

View File

@ -256,6 +256,7 @@ struct gsm_network *msc_network_alloc(void *ctx,
MSC_HLR_REMOTE_IP_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);
net->call_waiting = true;
net->lcls_permitted = false;
@ -546,6 +547,41 @@ extern void *tall_gsms_ctx;
extern void *tall_call_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 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)
return -1;
msc_network->mgw.client = mgcp_client_init(
msc_network, &msc_network->mgw.conf);
if (mgcp_client_connect(msc_network->mgw.client)) {
fprintf(stderr, "MGCPGW connect failed\n");
if (msc_mgw_setup() != 0)
return 7;
}
if (ss7_setup(tall_msc_ctx, &sccp_a, &sccp_iu)) {
fprintf(stderr, "Setting up SCCP client failed.\n");

View File

@ -1136,6 +1136,7 @@ static void run_tests(int nr)
struct gsm_network *test_net(void *ctx)
{
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_port = 0;
@ -1172,8 +1173,9 @@ struct gsm_network *test_net(void *ctx)
net->mgw.tdefs = g_mgw_tdefs;
mgcp_client_conf_init(&net->mgw.conf);
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;
}