From a3cdab448121c76a56ef547ffdc61e3f58a93dbc Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 9 May 2019 17:54:08 +0200 Subject: Request Osmux CID and forward it in Assign Req and Assign Compl Related: OS#2551 Depends: osmo-mgw.git I73b4c62baf39050da81d65553cbea07bc51163de Change-Id: I5b14e34481e890669c9ee02dba81eba84293cebb --- src/libmsc/call_leg.c | 4 ++++ src/libmsc/msc_a.c | 30 ++++++++++++++++++++++++++++-- src/libmsc/ran_msg_a.c | 23 ++++++++++++++++++++++- src/libmsc/rtp_stream.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 95 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/libmsc/call_leg.c b/src/libmsc/call_leg.c index 46405bcaa..794eda286 100644 --- a/src/libmsc/call_leg.c +++ b/src/libmsc/call_leg.c @@ -321,6 +321,10 @@ int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t cal if (call_leg_ensure_rtp_alloc(cl, dir, call_id, for_trans)) return -EIO; cl->rtp[dir]->crcx_conn_mode = cl->crcx_conn_mode[dir]; + if (dir == RTP_TO_RAN && cl->ran_peer_supports_osmux) { + cl->rtp[dir]->use_osmux = true; + cl->rtp[dir]->remote_osmux_cid = -1; /* wildcard */ + } if (codec_if_known) rtp_stream_set_codec(cl->rtp[dir], *codec_if_known); if (remote_addr_if_known && osmo_sockaddr_str_is_set(remote_addr_if_known)) diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c index cfba545be..b311df349 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -527,6 +527,8 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) .assignment_command = { .cn_rtp = &msc_a->cc.call_leg->rtp[RTP_TO_RAN]->local, .channel_type = &channel_type, + .osmux_present = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->use_osmux, + .osmux_cid = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->local_osmux_cid, }, }; if (msc_a_ran_down(msc_a, MSC_ROLE_I, &msg)) { @@ -620,8 +622,9 @@ static void msc_a_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, vo return; } LOG_MSC_A(msc_a, LOGL_DEBUG, - "MGW endpoint's RTP address available for the CI %s: " OSMO_SOCKADDR_STR_FMT "\n", - rtp_direction_name(rtps->dir), OSMO_SOCKADDR_STR_FMT_ARGS(&rtps->local)); + "MGW endpoint's RTP address available for the CI %s: " OSMO_SOCKADDR_STR_FMT " (osmux=%s:%d)\n", + rtp_direction_name(rtps->dir), OSMO_SOCKADDR_STR_FMT_ARGS(&rtps->local), + rtps->use_osmux ? "yes" : "no", rtps->local_osmux_cid); switch (rtps->dir) { case RTP_TO_RAN: msc_a_call_leg_ran_local_addr_available(msc_a); @@ -1257,9 +1260,20 @@ static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct return; } + if (rtps_to_ran->use_osmux != ac->assignment_complete.osmux_present) { + LOG_MSC_A_CAT(msc_a, DCC, LOGL_ERROR, "Osmux usage ass request and complete don't match: %d vs %d\n", + rtps_to_ran->use_osmux, ac->assignment_complete.osmux_present); + call_leg_release(msc_a->cc.call_leg); + return; + } + /* Update RAN-side endpoint CI: */ rtp_stream_set_codec(rtps_to_ran, ac->assignment_complete.codec); rtp_stream_set_remote_addr(rtps_to_ran, &ac->assignment_complete.remote_rtp); + if (rtps_to_ran->use_osmux) + rtp_stream_set_remote_osmux_cid(rtps_to_ran, + ac->assignment_complete.osmux_cid); + rtp_stream_commit(rtps_to_ran); /* Setup CN side endpoint CI: @@ -1592,6 +1606,8 @@ int msc_tx_common_id(struct msc_a *msc_a, enum msc_role to_role) static int msc_a_start_assignment(struct msc_a *msc_a, struct gsm_trans *cc_trans) { struct call_leg *cl = msc_a->cc.call_leg; + struct msc_i *msc_i = msc_a_msc_i(msc_a); + struct gsm_network *net = msc_a_net(msc_a); OSMO_ASSERT(!msc_a->cc.active_trans); msc_a->cc.active_trans = cc_trans; @@ -1612,6 +1628,16 @@ static int msc_a_start_assignment(struct msc_a *msc_a, struct gsm_trans *cc_tran cl->crcx_conn_mode[RTP_TO_RAN] = MGCP_CONN_LOOPBACK; } + if (net->use_osmux != OSMUX_USAGE_OFF) { + msc_i = msc_a_msc_i(msc_a); + if (msc_i->c.remote_to) { + /* TODO: investigate what to do in this case */ + LOG_MSC_A(msc_a, LOGL_ERROR, "Osmux not yet supported for inter-MSC"); + } else { + cl->ran_peer_supports_osmux = msc_i->ran_conn->ran_peer->remote_supports_osmux; + } + } + /* This will lead to either MSC_EV_CALL_LEG_LOCAL_ADDR_AVAILABLE or MSC_EV_CALL_LEG_TERM. * If the local address is already known, then immediately trigger. */ if (call_leg_local_ip(cl, RTP_TO_RAN)) diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c index 64590a1fe..fd8afdccd 100644 --- a/src/libmsc/ran_msg_a.c +++ b/src/libmsc/ran_msg_a.c @@ -269,6 +269,7 @@ static int ran_a_decode_assignment_complete(struct ran_dec *ran_dec, struct msgb { struct tlv_p_entry *ie_aoip_transp_addr = TLVP_GET(tp, GSM0808_IE_AOIP_TRASP_ADDR); struct tlv_p_entry *ie_speech_codec = TLVP_GET(tp, GSM0808_IE_SPEECH_CODEC); + struct tlv_p_entry *ie_osmux_cid = TLVP_GET(tp, GSM0808_IE_OSMO_OSMUX_CID); struct sockaddr_storage rtp_addr; struct sockaddr_in *rtp_addr_in; struct gsm0808_speech_codec sc; @@ -300,6 +301,15 @@ static int ran_a_decode_assignment_complete(struct ran_dec *ran_dec, struct msgb } } + if (ie_osmux_cid) { + rc = gsm0808_dec_osmux_cid(&ran_dec_msg.assignment_complete.osmux_cid, ie_osmux_cid->val, ie_osmux_cid->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Unable to decode Osmux CID\n"); + return -EINVAL; + } + ran_dec_msg.assignment_complete.osmux_present = true; + } + if (ie_speech_codec) { /* Decode Speech Codec (Chosen) element */ rc = gsm0808_dec_speech_codec(&sc, ie_speech_codec->val, ie_speech_codec->len); @@ -902,6 +912,13 @@ static int ran_a_channel_type_to_speech_codec_list(struct gsm0808_speech_codec_l return 0; } +static void _gsm0808_assignment_extend_osmux(struct msgb *msg, uint8_t cid) +{ + OSMO_ASSERT(msg->l3h[1] == msgb_l3len(msg) - 2); /*TL not in len */ + msgb_tv_put(msg, GSM0808_IE_OSMO_OSMUX_CID, cid); + msg->l3h[1] = msgb_l3len(msg) - 2; +} + /* Compose a BSSAP Assignment Command. * Passing an RTP address is optional. * The msub is passed merely for error logging. */ @@ -912,6 +929,7 @@ static struct msgb *ran_a_make_assignment_command(struct osmo_fsm_inst *log_fi, struct gsm0808_speech_codec_list *use_scl = NULL; struct sockaddr_storage rtp_addr; struct sockaddr_storage *use_rtp_addr = NULL; + struct msgb *msg; int rc; if (!ac->channel_type) { @@ -952,7 +970,10 @@ static struct msgb *ran_a_make_assignment_command(struct osmo_fsm_inst *log_fi, } } - return gsm0808_create_ass(ac->channel_type, NULL, use_rtp_addr, use_scl, NULL); + msg = gsm0808_create_ass(ac->channel_type, NULL, use_rtp_addr, use_scl, NULL); + if (ac->osmux_present) + _gsm0808_assignment_extend_osmux(msg, ac->osmux_cid); + return msg; } /* For an A5/N number a5_n set dst to the matching GSM0808_ALG_ID_A5_. */ diff --git a/src/libmsc/rtp_stream.c b/src/libmsc/rtp_stream.c index afe24ad51..c3880bf7b 100644 --- a/src/libmsc/rtp_stream.c +++ b/src/libmsc/rtp_stream.c @@ -82,11 +82,19 @@ void rtp_stream_update_id(struct rtp_stream *rtps) OSMO_STRBUF_PRINTF(sb, ":no-codec"); else if (!rtps->codec_sent_to_mgw) OSMO_STRBUF_PRINTF(sb, ":codec-not-sent"); + if (rtps->use_osmux) { + if (rtps->remote_osmux_cid < 0) + OSMO_STRBUF_PRINTF(sb, ":no-remote-osmux-cid"); + else if (!rtps->remote_osmux_cid_sent_to_mgw) + OSMO_STRBUF_PRINTF(sb, ":remote-osmux-cid-not-sent"); + } } if (osmo_sockaddr_str_is_set(&rtps->local)) OSMO_STRBUF_PRINTF(sb, ":local-%s-%u", rtps->local.ip, rtps->local.port); if (osmo_sockaddr_str_is_set(&rtps->remote)) OSMO_STRBUF_PRINTF(sb, ":remote-%s-%u", rtps->remote.ip, rtps->remote.port); + if (rtps->use_osmux) + OSMO_STRBUF_PRINTF(sb, ":osmux-%d-%d", rtps->local_osmux_cid, rtps->remote_osmux_cid); /* Replace any dots in the IP address, dots not allowed as FSM instance name */ for (p = buf; *p; p++) @@ -117,6 +125,8 @@ struct rtp_stream *rtp_stream_alloc(struct call_leg *parent_call_leg, enum rtp_d .call_id = call_id, .for_trans = for_trans, .dir = dir, + .local_osmux_cid = -2, + .remote_osmux_cid = -2, }; rtp_stream_update_id(rtps); @@ -130,6 +140,7 @@ static void check_established(struct rtp_stream *rtps) && osmo_sockaddr_str_is_set(&rtps->local) && osmo_sockaddr_str_is_set(&rtps->remote) && rtps->remote_sent_to_mgw + && (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) && rtps->codec_known) rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHED); } @@ -148,17 +159,27 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui } osmo_sockaddr_str_from_str(&rtps->local, crcx_info->addr, crcx_info->port); + if (rtps->use_osmux != crcx_info->x_osmo_osmux_use) { + LOG_RTPS(rtps, LOGL_ERROR, "Osmux usage request and response don't match: %d vs %d", + rtps->use_osmux, crcx_info->x_osmo_osmux_use); + /* TODO: proper failure path */ + OSMO_ASSERT(rtps->use_osmux != crcx_info->x_osmo_osmux_use); + } + if (crcx_info->x_osmo_osmux_use) + rtps->local_osmux_cid = crcx_info->x_osmo_osmux_cid; rtp_stream_update_id(rtps); osmo_fsm_inst_dispatch(fi->proc.parent, CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE, rtps); check_established(rtps); if ((!rtps->remote_sent_to_mgw || !rtps->codec_sent_to_mgw) && osmo_sockaddr_str_is_set(&rtps->remote) + && (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) && rtps->codec_known) { LOG_RTPS(rtps, LOGL_DEBUG, - "local ip:port set;%s%s triggering MDCX to send the new settings\n", + "local ip:port set;%s%s%s triggering MDCX to send the new settings\n", (!rtps->remote_sent_to_mgw)? " remote ip:port not yet sent," : "", - (!rtps->codec_sent_to_mgw)? " codec not yet sent," : ""); + (!rtps->codec_sent_to_mgw)? " codec not yet sent," : "", + (rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw) ? "Osmux CID not yet sent,": ""); rtp_stream_do_mdcx(rtps); } return; @@ -172,6 +193,7 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui case RTP_STREAM_EV_MDCX_FAIL: rtps->remote_sent_to_mgw = false; rtps->codec_sent_to_mgw = false; + rtps->remote_osmux_cid_sent_to_mgw = false; rtp_stream_update_id(rtps); rtp_stream_state_chg(rtps, RTP_STREAM_ST_DISCARDING); return; @@ -280,6 +302,8 @@ static int rtp_stream_do_mgcp_verb(struct rtp_stream *rtps, enum mgcp_verb verb, verb_info = (struct mgcp_conn_peer){ .call_id = rtps->call_id, .ptime = 20, + .x_osmo_osmux_use = rtps->use_osmux, + .x_osmo_osmux_cid = rtps->remote_osmux_cid, }; if (verb == MGCP_VERB_CRCX) @@ -353,9 +377,10 @@ int rtp_stream_commit(struct rtp_stream *rtps) return 0; } - LOG_RTPS(rtps, LOGL_DEBUG, "Committing: Tx MDCX to update the MGW: updating%s%s\n", + LOG_RTPS(rtps, LOGL_DEBUG, "Committing: Tx MDCX to update the MGW: updating%s%s%s\n", rtps->remote_sent_to_mgw ? "" : " remote-RTP-IP-port", - rtps->codec_sent_to_mgw ? "" : " codec"); + rtps->codec_sent_to_mgw ? "" : " codec", + (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) ? "" : " remote-Osmux-CID"); return rtp_stream_do_mdcx(rtps); } @@ -380,6 +405,16 @@ void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_socka rtp_stream_update_id(rtps); } +void rtp_stream_set_remote_osmux_cid(struct rtp_stream *rtps, uint8_t osmux_cid) +{ + if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED) + rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHING); + LOG_RTPS(rtps, LOGL_DEBUG, "setting remote Osmux CID to %u\n", osmux_cid); + rtps->remote_osmux_cid = osmux_cid; + rtps->remote_osmux_cid_sent_to_mgw = false; + rtp_stream_update_id(rtps); +} + bool rtp_stream_is_established(struct rtp_stream *rtps) { if (!rtps) @@ -389,7 +424,8 @@ bool rtp_stream_is_established(struct rtp_stream *rtps) if (rtps->fi->state != RTP_STREAM_ST_ESTABLISHED) return false; if (!rtps->remote_sent_to_mgw - || !rtps->codec_sent_to_mgw) + || !rtps->codec_sent_to_mgw + || (rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw)) return false; return true; } -- cgit v1.2.3