aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/lchan_rtp_fsm.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-04-23 18:37:37 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2019-04-30 02:24:18 +0200
commitf14aaa4ba1a744d74d431344e23932214bc42a08 (patch)
tree96951088d517116bc00f753a3b869b6d6550111c /src/osmo-bsc/lchan_rtp_fsm.c
parenta6078fe1d8701d15262e7eb5b3d50d13d1702bbc (diff)
move mgw endpoint FSM to osmo-mgw.git
osmo-mgw.git also includes fixes of the MGW endpoint FSM, for example I92a9944acc96398acd6649f9c3c5badec5dd6dcc. Depends: I9a3effd38e72841529df6c135c077116981dea36 (osmo-mgw) Change-Id: I03e6b48d9b0a5370310d5f56809259ff7909cf9d
Diffstat (limited to 'src/osmo-bsc/lchan_rtp_fsm.c')
-rw-r--r--src/osmo-bsc/lchan_rtp_fsm.c114
1 files changed, 99 insertions, 15 deletions
diff --git a/src/osmo-bsc/lchan_rtp_fsm.c b/src/osmo-bsc/lchan_rtp_fsm.c
index 5e2d75891..a5efa3d3d 100644
--- a/src/osmo-bsc/lchan_rtp_fsm.c
+++ b/src/osmo-bsc/lchan_rtp_fsm.c
@@ -21,11 +21,12 @@
*/
#include <osmocom/core/fsm.h>
+#include <osmocom/netif/rtp.h>
+#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
#include <osmocom/bsc/gsm_data.h>
#include <osmocom/bsc/lchan_fsm.h>
#include <osmocom/bsc/lchan_rtp_fsm.h>
-#include <osmocom/bsc/mgw_endpoint_fsm.h>
#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
#include <osmocom/bsc/abis_rsl.h>
#include <osmocom/bsc/bsc_msc_data.h>
@@ -120,7 +121,7 @@ void lchan_rtp_fsm_start(struct gsm_lchan *lchan)
/* While activating an lchan, for example for Handover, we may want to re-use another lchan's MGW
* endpoint CI. If Handover fails half way, the old lchan must keep its MGW endpoint CI, and we must not
* clean it up. Hence keep another lchan's mgw_endpoint_ci_bts out of lchan until all is done. */
-struct mgwep_ci *lchan_use_mgw_endpoint_ci_bts(struct gsm_lchan *lchan)
+struct osmo_mgcpc_ep_ci *lchan_use_mgw_endpoint_ci_bts(struct gsm_lchan *lchan)
{
if (lchan->mgw_endpoint_ci_bts)
return lchan->mgw_endpoint_ci_bts;
@@ -135,13 +136,13 @@ 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 mgw_endpoint *mgwep;
- struct mgwep_ci *use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan);
+ 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 = {};
if (use_mgwep_ci) {
LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "MGW endpoint already available: %s\n",
- mgwep_ci_name(use_mgwep_ci));
+ osmo_mgcpc_ep_ci_name(use_mgwep_ci));
lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_LCHAN_READY);
return;
}
@@ -152,7 +153,7 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in
return;
}
- lchan->mgw_endpoint_ci_bts = mgw_endpoint_ci_add(mgwep, "to-BTS");
+ lchan->mgw_endpoint_ci_bts = osmo_mgcpc_ep_ci_add(mgwep, "to-BTS");
if (lchan->conn) {
crcx_info.call_id = lchan->conn->sccp.conn_id;
@@ -162,7 +163,7 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in
crcx_info.ptime = 20;
mgcp_pick_codec(&crcx_info, lchan, true);
- mgw_endpoint_ci_request(lchan->mgw_endpoint_ci_bts, MGCP_VERB_CRCX, &crcx_info,
+ 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,
0);
}
@@ -174,7 +175,7 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available(struct osmo_fsm_inst *fi,
case LCHAN_RTP_EV_MGW_ENDPOINT_AVAILABLE:
LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "MGW endpoint: %s\n",
- mgwep_ci_name(lchan_use_mgw_endpoint_ci_bts(lchan)));
+ osmo_mgcpc_ep_ci_name(lchan_use_mgw_endpoint_ci_bts(lchan)));
lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_LCHAN_READY);
return;
@@ -328,7 +329,7 @@ static void lchan_rtp_fsm_wait_ipacc_mdcx_ack_onenter(struct osmo_fsm_inst *fi,
return;
}
- mgw_rtp = mgwep_ci_get_rtp_info(lchan_use_mgw_endpoint_ci_bts(lchan));
+ mgw_rtp = osmo_mgcpc_ep_ci_get_rtp_info(lchan_use_mgw_endpoint_ci_bts(lchan));
if (!mgw_rtp) {
lchan_rtp_fail("Cannot send IPACC MDCX to BTS:"
@@ -396,7 +397,7 @@ static void lchan_rtp_fsm_wait_ready_to_switch_rtp(struct osmo_fsm_inst *fi, uin
}
static void connect_mgw_endpoint_to_lchan(struct osmo_fsm_inst *fi,
- struct mgwep_ci *ci,
+ struct osmo_mgcpc_ep_ci *ci,
struct gsm_lchan *to_lchan)
{
int rc;
@@ -426,8 +427,8 @@ static void connect_mgw_endpoint_to_lchan(struct osmo_fsm_inst *fi,
}
LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "Sending BTS side RTP port info %s:%u to MGW %s\n",
- mdcx_info.addr, mdcx_info.port, mgwep_ci_name(ci));
- mgw_endpoint_ci_request(ci, MGCP_VERB_MDCX, &mdcx_info,
+ mdcx_info.addr, mdcx_info.port, osmo_mgcpc_ep_ci_name(ci));
+ osmo_mgcpc_ep_ci_request(ci, MGCP_VERB_MDCX, &mdcx_info,
fi, LCHAN_RTP_EV_MGW_ENDPOINT_CONFIGURED,
LCHAN_RTP_EV_MGW_ENDPOINT_ERROR, 0);
}
@@ -539,7 +540,7 @@ static void lchan_rtp_fsm_rollback(struct osmo_fsm_inst *fi, uint32_t event, voi
LOG_LCHAN_RTP(lchan, LOGL_ERROR,
"Error while connecting the MGW back to the old lchan's RTP port:"
" %s %s\n",
- mgwep_ci_name(lchan->mgw_endpoint_ci_bts),
+ osmo_mgcpc_ep_ci_name(lchan->mgw_endpoint_ci_bts),
gsm_lchan_name(old_lchan));
osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, 0);
return;
@@ -575,7 +576,7 @@ static void lchan_rtp_fsm_established(struct osmo_fsm_inst *fi, uint32_t event,
case LCHAN_RTP_EV_IPACC_MDCX_ACK:
LOG_LCHAN_RTP(lchan, LOGL_NOTICE,
"Received MDCX ACK on established lchan's RTP port: %s\n",
- mgwep_ci_name(lchan->mgw_endpoint_ci_bts));
+ osmo_mgcpc_ep_ci_name(lchan->mgw_endpoint_ci_bts));
return;
default:
OSMO_ASSERT(false);
@@ -740,7 +741,7 @@ void lchan_rtp_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause ca
{
struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi);
if (lchan->mgw_endpoint_ci_bts) {
- mgw_endpoint_ci_dlcx(lchan->mgw_endpoint_ci_bts);
+ osmo_mgcpc_ep_ci_dlcx(lchan->mgw_endpoint_ci_bts);
lchan->mgw_endpoint_ci_bts = NULL;
}
lchan->fi_rtp = NULL;
@@ -769,3 +770,86 @@ static struct osmo_fsm lchan_rtp_fsm = {
.timer_cb = lchan_rtp_fsm_timer_cb,
.cleanup = lchan_rtp_fsm_cleanup,
};
+
+/* Depending on the channel mode and rate, return the codec type that is signalled towards the MGW. */
+static enum mgcp_codecs chan_mode_to_mgcp_codec(enum gsm48_chan_mode chan_mode, bool full_rate)
+{
+ switch (chan_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ if (full_rate)
+ return CODEC_GSM_8000_1;
+ return CODEC_GSMHR_8000_1;
+
+ case GSM48_CMODE_SPEECH_EFR:
+ return CODEC_GSMEFR_8000_1;
+
+ case GSM48_CMODE_SPEECH_AMR:
+ return CODEC_AMR_8000_1;
+
+ default:
+ return -1;
+ }
+}
+
+static int chan_mode_to_mgcp_bss_pt(enum mgcp_codecs codec)
+{
+ switch (codec) {
+ case CODEC_GSMHR_8000_1:
+ return RTP_PT_GSM_HALF;
+
+ case CODEC_GSMEFR_8000_1:
+ return RTP_PT_GSM_EFR;
+
+ case CODEC_AMR_8000_1:
+ return RTP_PT_AMR;
+
+ default:
+ /* Not an error, we just leave it to libosmo-mgcp-client to
+ * decide over the PT. */
+ return -1;
+ }
+}
+
+void mgcp_pick_codec(struct mgcp_conn_peer *verb_info, const struct gsm_lchan *lchan, bool bss_side)
+{
+ enum mgcp_codecs codec = chan_mode_to_mgcp_codec(lchan->tch_mode,
+ lchan->type == GSM_LCHAN_TCH_H? false : true);
+ int custom_pt;
+
+ if (codec < 0) {
+ LOG_LCHAN(lchan, LOGL_ERROR,
+ "Unable to determine MGCP codec type for %s in chan-mode %s\n",
+ gsm_lchant_name(lchan->type), gsm48_chan_mode_name(lchan->tch_mode));
+ verb_info->codecs_len = 0;
+ return;
+ }
+
+ verb_info->codecs[0] = codec;
+ verb_info->codecs_len = 1;
+
+ /* Setup custom payload types (only for BSS side and when required) */
+ custom_pt = chan_mode_to_mgcp_bss_pt(codec);
+ if (bss_side && custom_pt > 0) {
+ verb_info->ptmap[0].codec = codec;
+ verb_info->ptmap[0].pt = custom_pt;
+ verb_info->ptmap_len = 1;
+ }
+
+ /* AMR requires additional parameters to be set up (framing mode) */
+ if (verb_info->codecs[0] == CODEC_AMR_8000_1) {
+ verb_info->param_present = true;
+ verb_info->param.amr_octet_aligned_present = true;
+ }
+
+ if (bss_side && verb_info->codecs[0] == CODEC_AMR_8000_1) {
+ /* FIXME: At the moment all BTSs we support are using the
+ * octet-aligned payload format. However, in the future
+ * we may support BTSs that are using bandwith-efficient
+ * format. In this case we will have to add functionality
+ * that distinguishes by the BTS model which mode to use. */
+ verb_info->param.amr_octet_aligned = true;
+ }
+ else if (!bss_side && verb_info->codecs[0] == CODEC_AMR_8000_1) {
+ verb_info->param.amr_octet_aligned = lchan->conn->sccp.msc->amr_octet_aligned;
+ }
+}