Introduce support for MGW-pinning per BTS
This feature allows pinning each BTS to a specific MGW from the configured pool. The pinning can be soft or hard (strict). If strict pinning is not set, the configured MGW is selected with priority, but other MGWs can still be selected during each call setup if the preferred MGW is found not available at that time, hence avoiding denial of service for the entire BTS if that MGW goes down. If strict mode is selected, the call will be refused if the configured preferred MGW is not available at the time the call is set up. It is useful to use this feature when Osmux is configured between the BTS and the BSC and an MGW pool is in use. This way the BSC is capable of grouping all the calls of a BTS towards one MGW, hence taking advantage of the Osmux trunking optimizations to reduce link data usage (AMR payload of several concurrent calls ending up sharing the same underlaying UPD packet). Furthermore, this allows the operator to intelligently spread load over the MGW pool in order to avoid ending up with more than 256 concurrent Osmux circuits on any of the co-located MGWs in the pool (maximum supported at the moment). Related: SYS#5987 Depends: osmo-mgw.git 5d8b5b093595e1203e288c3175c163c0994b1102 Change-Id: I9a7a5af72795faed0d12d9d73b59951b6a0e9c7d
This commit is contained in:
parent
ad27ef2b15
commit
0690c5bc75
|
@ -9,3 +9,4 @@
|
|||
#library what description / commit summary line
|
||||
libosmogsm >1.7.0 BTS_FEAT_OSMUX, RSL_IE_OSMO_OSMUX_CID
|
||||
libosmocore >1.7.0 vty hexadecimal range support (location_area_code)
|
||||
libosmomgcp-client >1.10.0 mgcp_client_pool_member_...()
|
||||
|
|
|
@ -250,3 +250,52 @@ OsmoBSC# configure terminal
|
|||
OsmoBSC(config)# network
|
||||
OsmoBSC(config-net)# no mgw 2
|
||||
----
|
||||
|
||||
==== Pinning a BTS to a specific MGW
|
||||
|
||||
It is sometimes desirable to assign a specific MGW to a given BTS, so that all
|
||||
calls where the BTS is involved use the assigned MGW with a higher precedence if
|
||||
possible.
|
||||
|
||||
This is specially important if the BTS is configured to serve calls using Osmux
|
||||
instead of RTP. Osmux features trunking optimizations, which allow transmission
|
||||
of audio payload from different concurrent calls inside the same underlaying UDP
|
||||
packet, hence reducing the total required throughput and saving costs on the
|
||||
required link.
|
||||
|
||||
In order for Osmux trunking optimization to work, the source and destination IP
|
||||
address of uderlaying UDP packet must be of course the same for all the calls
|
||||
involved. That essentially boils down to having all the concurrent calls of the
|
||||
BTS be connected to the same MGW so that they can be trunked over the same UDP
|
||||
connection.
|
||||
|
||||
The pinning to a specific MGW can be configured per BTS, and hence it is
|
||||
configured under the `bts` VTY node:
|
||||
|
||||
----
|
||||
OsmoBSC> enable
|
||||
OsmoBSC# configure terminal
|
||||
OsmoBSC(config)# network
|
||||
OsmoBSC(config-net)# bts 1
|
||||
OsmoBSC(config-bts)# mgw pool-target 1 <1>
|
||||
OsmoBSC(config-bts)# exit
|
||||
OsmoBSC(config-net)# bts 2
|
||||
OsmoBSC(config-mgw)# mgw pool-target 7 strict <2>
|
||||
OsmoBSC(config-net)# bts 3
|
||||
OsmoBSC(config-mgw)# no mgw pool-target <3>
|
||||
----
|
||||
|
||||
<1> Pin BTS1 to prefer MGW1 (node `mgw 1`). If MGW1 is not configured,
|
||||
administrateivly blocked or not connected at the time a new call is to be
|
||||
established, then another MGW from the pool is selected following the usual
|
||||
procedures. This allows applying pinning in the usual scenario while still
|
||||
keeping call service ongoing against another MGW if the preferred MGW is not
|
||||
available at a given time.
|
||||
|
||||
<2> Pin BTS2 to prefer MGW3 (node `mgw 7`). If MGW7 is not configured,
|
||||
administrateivly blocked or not connected at the time a new call is to be
|
||||
established, then the MGW assignment will fail and ultimately the call will be
|
||||
terminated during establishment.
|
||||
|
||||
<3> Apply no pinning at all (default). The MGW with the lowest load is the one
|
||||
being selected for each new call.
|
||||
|
|
|
@ -580,6 +580,10 @@ struct gsm_bts {
|
|||
/* exclude the BTS from the global RF Lock handling */
|
||||
int excl_from_rf_lock;
|
||||
|
||||
/* MGW specificities for this BTS: */
|
||||
int mgw_pool_target; /* Pin to specific MGW. -1 = wildcard */
|
||||
bool mgw_pool_target_strict; /* Only allow pinned MGW */
|
||||
|
||||
/* supported codecs beside FR */
|
||||
struct bts_codec_conf codec;
|
||||
|
||||
|
|
|
@ -621,6 +621,62 @@ static bool same_mgw_info(const struct mgcp_conn_peer *a, const struct mgcp_conn
|
|||
return true;
|
||||
}
|
||||
|
||||
static struct mgcp_client *select_mgw(struct gsm_subscriber_connection *conn, struct gsm_lchan *for_lchan)
|
||||
{
|
||||
struct mgcp_client_pool_member *mgcp_pmemb;
|
||||
struct mgcp_client *mgcp_client;
|
||||
struct gsm_bts *bts = for_lchan->ts->trx->bts;
|
||||
|
||||
/* If BTS is not pinned to a given MGW, let regular allocation which
|
||||
* spreads load over available MGWs: */
|
||||
if (bts->mgw_pool_target == -1)
|
||||
goto pick_any;
|
||||
|
||||
/* BTS is pinned to an MGW, retrieve pointer to it: */
|
||||
mgcp_pmemb = mgcp_client_pool_find_member_by_nr(conn->network->mgw.mgw_pool, bts->mgw_pool_target);
|
||||
if (!mgcp_pmemb) {
|
||||
if (!bts->mgw_pool_target_strict) {
|
||||
LOGPFSML(conn->fi, LOGL_NOTICE,
|
||||
"mgw pool-target %u not found! selecting another one.\n", bts->mgw_pool_target);
|
||||
goto pick_any;
|
||||
} else {
|
||||
LOGPFSML(conn->fi, LOGL_ERROR, "mgw pool-target %u not found!\n", bts->mgw_pool_target);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (mgcp_client_pool_member_is_blocked(mgcp_pmemb)) {
|
||||
if (!bts->mgw_pool_target_strict) {
|
||||
LOGPFSML(conn->fi, LOGL_NOTICE,
|
||||
"mgw pool-target %u is administratively blocked! selecting another one.\n",
|
||||
bts->mgw_pool_target);
|
||||
goto pick_any;
|
||||
} else {
|
||||
LOGPFSML(conn->fi, LOGL_ERROR, "mgw pool-target %u is administratively blocked!\n",
|
||||
bts->mgw_pool_target);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mgcp_client = mgcp_client_pool_member_get(mgcp_pmemb);
|
||||
if (!mgcp_client) {
|
||||
if (!bts->mgw_pool_target_strict) {
|
||||
LOGPFSML(conn->fi, LOGL_NOTICE,
|
||||
"mgw pool-target %u is not connected! selecting another one.\n",
|
||||
bts->mgw_pool_target);
|
||||
goto pick_any;
|
||||
} else {
|
||||
LOGPFSML(conn->fi, LOGL_ERROR, "mgw pool-target %u is not connected!\n",
|
||||
bts->mgw_pool_target);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return mgcp_client;
|
||||
|
||||
pick_any:
|
||||
mgcp_client = mgcp_client_pool_get(conn->network->mgw.mgw_pool);
|
||||
return mgcp_client;
|
||||
}
|
||||
|
||||
/* Make sure a conn->user_plane.mgw_endpoint is allocated with the proper mgw endpoint name. For
|
||||
* SCCPlite, pass in msc_assigned_cic the CIC received upon BSSMAP Assignment Command or BSSMAP Handover
|
||||
* Request form the MSC (which is only stored in conn->user_plane after success). Ignored for AoIP. */
|
||||
|
@ -640,7 +696,7 @@ struct osmo_mgcpc_ep *gscon_ensure_mgw_endpoint(struct gsm_subscriber_connection
|
|||
|
||||
if (gscon_is_sccplite(conn) || gscon_is_aoip(conn)) {
|
||||
/* Get MGCP client from pool */
|
||||
mgcp_client = mgcp_client_pool_get(conn->network->mgw.mgw_pool);
|
||||
mgcp_client = select_mgw(conn, for_lchan);
|
||||
if (!mgcp_client) {
|
||||
LOGPFSML(conn->fi, LOGL_ERROR,
|
||||
"cannot ensure MGW endpoint -- no MGW configured, check configuration!\n");
|
||||
|
|
|
@ -331,6 +331,9 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, struct gsm_bts_sm *bts_sm
|
|||
INIT_LLIST_HEAD(&bts->oml_fail_rep);
|
||||
INIT_LLIST_HEAD(&bts->chan_rqd_queue);
|
||||
|
||||
/* Don't pin the BTS to any MGW by default: */
|
||||
bts->mgw_pool_target = -1;
|
||||
|
||||
/* Enable all codecs by default. These get reset to a more fine grained selection IF a
|
||||
* 'codec-support' config appears in the config file (see bsc_vty.c). */
|
||||
bts->codec = (struct bts_codec_conf){
|
||||
|
|
|
@ -3000,6 +3000,36 @@ err:
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
DEFUN_USRATTR(cfg_bts_mgw_pool_target,
|
||||
cfg_bts_mgw_pool_target_cmd,
|
||||
X(BSC_VTY_ATTR_NEW_LCHAN),
|
||||
"mgw pool-target <0-255> [strict]",
|
||||
"MGW configuration for this specific BTS\n"
|
||||
"Pin BTS to use a single MGW in the pool\n"
|
||||
"Reference Number of the MGW (in the config) to pin to\n"
|
||||
"Strictly prohibit use of other MGWs if the pinned one is not available\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int mgw_nr = atoi(argv[0]);
|
||||
bool strict = argc > 1;
|
||||
bts->mgw_pool_target = mgw_nr;
|
||||
bts->mgw_pool_target_strict = strict;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_USRATTR(cfg_bts_no_mgw_pool_target,
|
||||
cfg_bts_no_mgw_pool_target_cmd,
|
||||
X(BSC_VTY_ATTR_NEW_LCHAN),
|
||||
"no mgw pool-target",
|
||||
NO_STR "MGW configuration for this specific BTS\n"
|
||||
"Avoid pinning the BTS to any specific MGW (default)\n")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->mgw_pool_target = -1;
|
||||
bts->mgw_pool_target_strict = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define TNUM_STR "T-number, optionally preceded by 't' or 'T'\n"
|
||||
DEFUN_ATTR(cfg_bts_t3113_dynamic, cfg_bts_t3113_dynamic_cmd,
|
||||
"timer-dynamic TNNNN",
|
||||
|
@ -4552,6 +4582,13 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
|||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (bts->mgw_pool_target > -1) {
|
||||
vty_out(vty, " mgw pool-target %u%s%s",
|
||||
bts->mgw_pool_target,
|
||||
bts->mgw_pool_target_strict ? " strict" : "",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
config_write_bts_gprs(vty, bts);
|
||||
|
||||
if (bts->excl_from_rf_lock)
|
||||
|
@ -4814,6 +4851,8 @@ int bts_vty_init(void)
|
|||
install_element(BTS_NODE, &cfg_bts_amr_hr_hyst3_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_amr_hr_start_mode_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_osmux_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_mgw_pool_target_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_no_mgw_pool_target_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_pcu_sock_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_acc_rotate_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_acc_rotate_quantum_cmd);
|
||||
|
|
Loading…
Reference in New Issue