neels has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-msc/+/37272?usp=email )

Change subject: do not invoke two Assignments (fixup for re-assignment)
......................................................................

do not invoke two Assignments (fixup for re-assignment)

Make sure we wait for Assignment responses before dispatching an
Assignment Request towards RAN.

In particular, when the remote call leg sends its codecs, we may trigger
Re-Assignment to match that codec. Make sure this is done only once:
when receiving another SDP message, wait for the first Assignment.

Implement as an osmo_timer, since there still is no osmo_fsm
implementation for Assignment nor for CC trans FSM. Also it doesn't
belong in the msc_a FSM (it should remain in state COMMUNICATING).

Without this patch, new ttcn3 test TC_lu_and_mo_call_reass_for_mt_codec
sporadically fails, if MNCC with SDP falls in-between Assignment Request
and Assignment Complete.

Related: osmo-msc d767c73a1f93253a54d6a8650a4cf2143353bba0 == 
I8760feaa8598047369ef8c3ab2673013bac8ac8a
Related: osmo-ttcn3-hacks I402ed0523a2a87b83f29c5577b2c828102005d53
Change-Id: I0f1e1a551aed545b555b9f236fc5967b1e4cc940
---
M include/osmocom/msc/msc_a.h
M src/libmsc/gsm_04_08_cc.c
M src/libmsc/msc_a.c
M src/libmsc/ran_infra.c
4 files changed, 75 insertions(+), 1 deletion(-)

Approvals:
  fixeria: Looks good to me, but someone else must approve
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified
  neels: Looks good to me, approved




diff --git a/include/osmocom/msc/msc_a.h b/include/osmocom/msc/msc_a.h
index a5b624c..d180e38 100644
--- a/include/osmocom/msc/msc_a.h
+++ b/include/osmocom/msc/msc_a.h
@@ -137,6 +137,8 @@
                /* There may be up to 7 incoming calls for this subscriber. 
This is the currently serviced voice call,
                 * as in, the other person the subscriber is currently talking 
to. */
                struct gsm_trans *active_trans;
+
+               struct osmo_timer_list assignment_request_pending;
        } cc;

        struct msc_ho_state ho;
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index 63b1699..fc4f730 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -772,7 +772,8 @@
                        const struct gsm_mncc_bearer_cap *bcap)
 {
        struct codec_filter *codecs = &trans->cc.codecs;
-       struct call_leg *cl = trans->msc_a ? trans->msc_a->cc.call_leg : NULL;
+       struct msc_a *msc_a = trans->msc_a;
+       struct call_leg *cl = msc_a ? msc_a->cc.call_leg : NULL;
        struct rtp_stream *rtp_cn = cl ? cl->rtp[RTP_TO_CN] : NULL;

        if (sdp[0]) {
@@ -818,6 +819,16 @@
                return;
        }

+       if (msc_a && osmo_timer_pending(&msc_a->cc.assignment_request_pending)) 
{
+               /* Still waiting for an Assignment Response.
+                * For example, when the remote call leg sends some MNCC with 
SDP with a mismatching codec,
+                * we start Re-Assignment to match that codec: we send an 
Assignment Request and wait for a response.
+                * When we receive another MNCC with SDP from the remote call 
leg before this Re-Assignment is
+                * completed, we must not trigger *another* Assignment Request, 
but instead wait for the Re-Assignment
+                * to come back with a response first. */
+               return;
+       }
+
        /* We've already completed Assignment of a voice channel (some time 
ago), and now the remote side has changed
         * to a mismatching codec (list). Try to re-assign this side to a 
matching codec. */
        LOG_TRANS(trans, LOGL_INFO, "Remote call leg mismatches assigned codec: 
%s\n",
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index bff5e67..2e88a32 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -673,6 +673,8 @@
                                  rtp_to_ran->codecs_known ? 
&rtp_to_ran->codecs : NULL, NULL);
 }

+static void assignment_request_timeout_cb(void *data);
+
 /* The MGW has given us a local IP address for the RAN side. Ready to start 
the Assignment of a voice channel. */
 void msc_a_tx_assignment_cmd(struct msc_a *msc_a)
 {
@@ -680,6 +682,19 @@
        struct gsm_trans *cc_trans = msc_a->cc.active_trans;
        struct gsm0808_channel_type channel_type;

+       /* Do not dispatch another Assignment Command before an earlier 
assignment is completed. This is a sanity
+        * safeguard, ideally callers should not even invoke this function when 
an Assignment is already ongoing.
+        * (There is no osmo_fsm for Assignment / the CC trans code; when we 
refactor that one day, this timer should be
+        * an FSM state.) */
+       if (osmo_timer_pending(&msc_a->cc.assignment_request_pending)) {
+               LOG_MSC_A(msc_a, LOGL_ERROR,
+                         "Not transmitting Assignment, still waiting for the 
response to an earlier Assignment\n");
+               return;
+       }
+       osmo_timer_setup(&msc_a->cc.assignment_request_pending, 
assignment_request_timeout_cb, msc_a);
+       osmo_timer_schedule(&msc_a->cc.assignment_request_pending,
+                           osmo_tdef_get(msc_a->c.ran->tdefs, -37, 
OSMO_TDEF_S, 10), 0);
+
        if (!cc_trans) {
                LOG_MSC_A(msc_a, LOGL_ERROR, "No CC transaction active\n");
                call_leg_release(msc_a->cc.call_leg);
@@ -943,6 +958,9 @@
                vlr_subscr_enable_expire_lu(vsub);
        }

+       /* We no longer care about assignment responses. */
+       osmo_timer_del(&msc_a->cc.assignment_request_pending);
+
        /* If we're closing in a middle of a trans, we need to clean up */
        trans_conn_closed(msc_a);

@@ -1051,6 +1069,7 @@
                vsub->msc_conn_ref = NULL;

        osmo_timer_del(&msc_a->lu_delay_timer);
+       osmo_timer_del(&msc_a->cc.assignment_request_pending);
 }

 const struct value_string msc_a_fsm_event_names[] = {
@@ -1479,6 +1498,9 @@
        const struct gsm0808_speech_codec *codec_if_known = 
ac->assignment_complete.codec_present ?
                                                            
&ac->assignment_complete.codec : NULL;

+       /* Pending assignment has worked out. We're no longer waiting for a 
response now. */
+       osmo_timer_del(&msc_a->cc.assignment_request_pending);
+
        /* For a voice group call, handling is performed by VGCS FSM */
        gcc_trans = trans_find_by_type(msc_a, TRANS_GCC);
        if (gcc_trans) {
@@ -1582,10 +1604,15 @@
        }
 }

+/* Invoked when Assignment has failed, either by a failure response, or by 
timeout. When failing on timeout,
+ * pass af == NULL. */
 static void msc_a_up_call_assignment_failure(struct msc_a *msc_a, const struct 
ran_msg *af)
 {
        struct gsm_trans *trans;

+       /* Pending assignment has failed. We're no longer waiting for a 
response now. */
+       osmo_timer_del(&msc_a->cc.assignment_request_pending);
+
        /* For a normal voice call, there will be an rtp_stream FSM. */
        if (msc_a->cc.call_leg && msc_a->cc.call_leg->rtp[RTP_TO_RAN]) {
                LOG_MSC_A(msc_a, LOGL_ERROR, "Assignment Failure, releasing 
call\n");
@@ -1617,6 +1644,12 @@
        msc_a_release_cn(msc_a);
 }

+static void assignment_request_timeout_cb(void *data)
+{
+       struct msc_a *msc_a = data;
+       msc_a_up_call_assignment_failure(msc_a, NULL);
+}
+
 static void msc_a_up_classmark_update(struct msc_a *msc_a, const struct 
osmo_gsm48_classmark *classmark,
                                      struct osmo_gsm48_classmark *dst)
 {
diff --git a/src/libmsc/ran_infra.c b/src/libmsc/ran_infra.c
index 79de7d2..0656cca 100644
--- a/src/libmsc/ran_infra.c
+++ b/src/libmsc/ran_infra.c
@@ -47,6 +47,8 @@
        { .T = -36, .default_val = 0, .unit = OSMO_TDEF_MS, \
          .desc = "Delay connection release after LU.  Useful to optimize an 
SMSC to dispatch " \
                  "pending messages within the initial connection." }, \
+       { .T = -37, .default_val = 10, \
+         .desc = "Voice channel Assignment sanity timeout, when no response is 
received (should never happen)." }, \

 struct osmo_tdef msc_tdefs_geran[] = {
        RAN_TDEFS

--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/37272?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: I0f1e1a551aed545b555b9f236fc5967b1e4cc940
Gerrit-Change-Number: 37272
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofm...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de>
Gerrit-Reviewer: neels <nhofm...@sysmocom.de>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>
Gerrit-MessageType: merged

Reply via email to