Add Osmux support on the Abis-side data plane

Related: SYS#5987
Change-Id: I48483b278ff829ee29d3e7fbcab0dd3a54728825
This commit is contained in:
Pau Espin 2022-08-08 13:50:39 +02:00
parent b2c7d0ab32
commit d8b5bf08e8
7 changed files with 111 additions and 6 deletions

View File

@ -7,3 +7,4 @@
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
libosmogsm >1.7.0 BTS_FEAT_OSMUX, RSL_IE_OSMO_OSMUX_CID

View File

@ -590,6 +590,9 @@ struct gsm_bts {
struct amr_multirate_conf mr_full;
struct amr_multirate_conf mr_half;
/* osmux config: */
enum osmux_usage use_osmux;
/* PCU socket state */
char *pcu_sock_path;
struct pcu_sock_state *pcu_state;

View File

@ -299,6 +299,12 @@ struct gsm_lchan {
uint8_t rr_cause;
bool valid;
} ass_compl;
struct {
bool use;
uint8_t local_cid;
uint8_t remote_cid;
} osmux;
} abis_ip;
/* At first, the Timing Advance from the initial Channel Request. Later, the Timing Advance value received from

View File

@ -2739,11 +2739,15 @@ static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv, const
port = ntohs(port);
lchan->abis_ip.connect_port = port;
}
if (TLVP_PRESENT(tv, RSL_IE_OSMO_OSMUX_CID)) {
lchan->abis_ip.osmux.remote_cid = tlvp_val8(tv, RSL_IE_OSMO_OSMUX_CID, 0);
}
LOG_LCHAN(lchan, LOGL_DEBUG, "Rx IPACC %s ACK:"
" BTS=%s:%u conn_id=%u rtp_payload2=0x%02x speech_mode=0x%02x\n",
" BTS=%s:%u conn_id=%u rtp_payload2=0x%02x speech_mode=0x%02x osmux_use=%d osmux_loc_cid=%d\n",
label, ip_to_a(lchan->abis_ip.bound_ip), lchan->abis_ip.bound_port,
lchan->abis_ip.conn_id, lchan->abis_ip.rtp_payload2, lchan->abis_ip.speech_mode);
lchan->abis_ip.conn_id, lchan->abis_ip.rtp_payload2, lchan->abis_ip.speech_mode,
lchan->abis_ip.osmux.use, lchan->abis_ip.osmux.local_cid);
}
/*! Send Issue IPA RSL CRCX to configure the RTP port of the BTS.
@ -2768,9 +2772,13 @@ int rsl_tx_ipacc_crcx(const struct gsm_lchan *lchan)
/* 0x1- == receive-only, 0x-1 == EFR codec */
msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
if (lchan->abis_ip.osmux.use)
msgb_tlv_put(msg, RSL_IE_OSMO_OSMUX_CID, 1, &lchan->abis_ip.osmux.local_cid);
LOG_LCHAN(lchan, LOGL_DEBUG, "Sending IPACC CRCX to BTS: speech_mode=0x%02x RTP_PAYLOAD=%d\n",
lchan->abis_ip.speech_mode, lchan->abis_ip.rtp_payload);
LOG_LCHAN(lchan, LOGL_DEBUG,
"Sending IPACC CRCX to BTS: speech_mode=0x%02x RTP_PAYLOAD=%d osmux_use=%d osmux_loc_cid=%d\n",
lchan->abis_ip.speech_mode, lchan->abis_ip.rtp_payload,
lchan->abis_ip.osmux.use, lchan->abis_ip.osmux.local_cid);
msg->dst = rsl_chan_link(lchan);
@ -2808,6 +2816,8 @@ struct msgb *rsl_make_ipacc_mdcx(const struct gsm_lchan *lchan, uint32_t dest_ip
msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
if (lchan->abis_ip.rtp_payload2)
msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, lchan->abis_ip.rtp_payload2);
if (lchan->abis_ip.osmux.use)
msgb_tlv_put(msg, RSL_IE_OSMO_OSMUX_CID, 1, &lchan->abis_ip.osmux.local_cid);
msg->dst = rsl_chan_link(lchan);
@ -2865,6 +2875,15 @@ static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
return -EINVAL;
}
if (!lchan->abis_ip.osmux.use && TLVP_PRESENT(&tv, RSL_IE_OSMO_OSMUX_CID)) {
LOGP(DRSL, LOGL_NOTICE, "Received unexpected IE Osmux CID\n");
return -EINVAL;
}
if (lchan->abis_ip.osmux.use && !TLVP_PRESENT(&tv, RSL_IE_OSMO_OSMUX_CID)) {
LOGP(DRSL, LOGL_NOTICE, "Mandatory IE Osmux CID missing\n");
return -EINVAL;
}
ipac_parse_rtp(lchan, &tv, "CRCX");
osmo_fsm_inst_dispatch(lchan->fi_rtp, LCHAN_RTP_EV_IPACC_CRCX_ACK, 0);

View File

@ -428,6 +428,8 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, struct gsm_bts_sm *bts_sm
memcpy(&bts->mr_half.bts_mode[0], &amr_hr_ms_bts_mode[0], sizeof(amr_hr_ms_bts_mode));
bts->mr_half.num_modes = ARRAY_SIZE(amr_hr_ms_bts_mode);
bts->use_osmux = OSMUX_USAGE_OFF;
bts_cbch_init(bts);
bts_etws_init(bts);
@ -507,6 +509,13 @@ int gsm_bts_check_cfg(struct gsm_bts *bts)
bts_gprs_mode_name(bts->gprs.mode));
return -EINVAL;
}
if (bts->use_osmux == OSMUX_USAGE_ONLY &&
!osmo_bts_has_feature(&bts->features, BTS_FEAT_OSMUX)) {
LOGP(DNM, LOGL_ERROR,
"(bts=%u) osmux use set to 'only', but BTS does not support Osmux\n",
bts->nr);
return -EINVAL;
}
}
/* Verify the physical channel mapping */

View File

@ -2965,6 +2965,42 @@ DEFUN_USRATTR(cfg_bts_amr_hr_hyst3,
return check_amr_config(vty);
}
#define OSMUX_STR "RTP multiplexing\n"
DEFUN_USRATTR(cfg_bts_osmux,
cfg_bts_osmux_cmd,
X(BSC_VTY_ATTR_NEW_LCHAN),
"osmux (on|off|only)",
OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
{
struct gsm_bts *bts = vty->index;
enum osmux_usage use;
if (strcmp(argv[0], "off") == 0)
use = OSMUX_USAGE_OFF;
else if (strcmp(argv[0], "on") == 0)
use = OSMUX_USAGE_ON;
else if (strcmp(argv[0], "only") == 0)
use = OSMUX_USAGE_ONLY;
else
goto err;
if (!is_osmobts(bts))
goto err;
if (bts->features_known && use != OSMUX_USAGE_OFF &&
!osmo_bts_has_feature(&bts->features, BTS_FEAT_OSMUX))
goto err;
bts->use_osmux = use;
return CMD_SUCCESS;
err:
LOGP(DNM, LOGL_ERROR,
"(bts=%u) Unable to set 'osmux %s', BTS does not support Osmux\n",
bts->nr, argv[0]);
return CMD_WARNING;
}
#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",
@ -4512,6 +4548,11 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
config_write_bts_amr(vty, bts, &bts->mr_full, 1);
config_write_bts_amr(vty, bts, &bts->mr_half, 0);
if (bts->use_osmux != OSMUX_USAGE_OFF) {
vty_out(vty, " osmux %s%s", bts->use_osmux == OSMUX_USAGE_ON ? "on" : "only",
VTY_NEWLINE);
}
config_write_bts_gprs(vty, bts);
if (bts->excl_from_rf_lock)
@ -4773,6 +4814,7 @@ int bts_vty_init(void)
install_element(BTS_NODE, &cfg_bts_amr_hr_hyst2_cmd);
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_pcu_sock_cmd);
install_element(BTS_NODE, &cfg_bts_acc_rotate_cmd);
install_element(BTS_NODE, &cfg_bts_acc_rotate_quantum_cmd);

View File

@ -138,9 +138,10 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in
uint32_t prev_state)
{
struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
struct gsm_bts *bts = lchan->ts->trx->bts;
struct osmo_mgcpc_ep *mgwep;
struct osmo_mgcpc_ep_ci *use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
struct mgcp_conn_peer crcx_info = {};
struct mgcp_conn_peer crcx_info;
if (!is_ipaccess_bts(lchan->ts->trx->bts)) {
LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "Audio link to-BTS via E1, skipping IPACC\n");
@ -163,13 +164,20 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in
lchan->mgw_endpoint_ci_bts = osmo_mgcpc_ep_ci_add(mgwep, "to-BTS");
crcx_info = (struct mgcp_conn_peer){
.ptime = 20,
.x_osmo_osmux_use = bts->use_osmux != OSMUX_USAGE_OFF,
.x_osmo_osmux_cid = -1, /* -1 is wildcard */
};
if (lchan->conn) {
crcx_info.call_id = lchan->conn->sccp.conn_id;
if (lchan->conn->sccp.msc)
crcx_info.x_osmo_ign = lchan->conn->sccp.msc->x_osmo_ign;
}
crcx_info.ptime = 20;
mgcp_pick_codec(&crcx_info, lchan, true);
/* TODO: lchan_rtp_fail() here if crcx_info->codecs[] contains non-AMR and bts->use_osmux=ONLY.
If bts->use_osmux=ON, only set .x_osmo_osmux_use if there's an AMR in crcx_info->codecs[].
IF osmux=no, always set x_osmo_osmux_use=false*/
osmo_mgcpc_ep_ci_request(lchan->mgw_endpoint_ci_bts, MGCP_VERB_CRCX, &crcx_info,
fi, LCHAN_RTP_EV_MGW_ENDPOINT_AVAILABLE, LCHAN_RTP_EV_MGW_ENDPOINT_ERROR,
@ -179,11 +187,26 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in
static void lchan_rtp_fsm_wait_mgw_endpoint_available(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
struct gsm_bts *bts = lchan->ts->trx->bts;
switch (event) {
case LCHAN_RTP_EV_MGW_ENDPOINT_AVAILABLE:
LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "MGW endpoint: %s\n",
osmo_mgcpc_ep_ci_name(lchan_use_mgw_endpoint_ci_bts(lchan)));
if (osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(lchan->mgw_endpoint_ci_bts,
&lchan->abis_ip.osmux.local_cid)) {
if (bts->use_osmux == OSMUX_USAGE_OFF) {
lchan_rtp_fail("Got Osmux CID from MGW but we didn't ask for it");
return;
}
lchan->abis_ip.osmux.use = true;
} else {
if (bts->use_osmux == OSMUX_USAGE_ONLY) {
lchan_rtp_fail("Got no Osmux CID from MGW but Osmux is mandatory");
return;
}
lchan->abis_ip.osmux.use = false;
}
lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_LCHAN_READY);
return;
@ -415,6 +438,8 @@ static void connect_mgw_endpoint_to_lchan(struct osmo_fsm_inst *fi,
mdcx_info = (struct mgcp_conn_peer){
.port = to_lchan->abis_ip.bound_port,
.ptime = 20,
.x_osmo_osmux_use = lchan->abis_ip.osmux.use,
.x_osmo_osmux_cid = lchan->abis_ip.osmux.remote_cid,
};
mgcp_pick_codec(&mdcx_info, to_lchan, true);