<div dir="ltr"><div>Hello Neels,</div><div><br></div><div>Firstly, I want to start from the background of these patches, I think it will help to understand their current status.</div><div>Some time ago we enabled HO on one of our production systems and figured out that many calls were dropped or we had other issues during the handover procedure.<br></div><div>We reproduced these cases in our lab and figured out that osmo-nitb didn't handle HO procedure during the establishment of the call in a proper way.<br></div><div>We fixed issues for the cases which we saw in our production system, also I tried to reproduce other HO issues during call establishing.</div><div>Unfortunately, I didn't implement any automated test suite for these HO procedure cases.</div><div>For tests, I called bsc_handover_start function from different parts of the code and for different states of the call and checked media and signalling after and during HO procedure.</div><div>So one of the main improvement which should be implemented is an automated test suite for HO procedure which will cover all stages of the call.</div><div><br></div><div>See my answers below:</div><div><br></div><div class="gmail_extra"><div class="gmail_quote">2018-01-16 0:45 GMT+03:00 Neels Hofmeyr <span dir="ltr"><<a href="mailto:nhofmeyr@sysmocom.de">nhofmeyr@sysmocom.de</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Ivan,<br>
<br>
as I'm working towards load-based handover and incorporating your patches, I<br>
found that most of it is concerned with libmsc. In contrast, I am currently<br>
working on osmo-bsc, in libbsc, and would like to ask your advice.<br>
<br>
Some parts of the patch aren't easy to understand for me, and I'd like to make<br>
sure that I am not dismissing parts of it as non-applicable to libbsc even<br>
though they might be important.<br>
<br>
Since your patches were written, the code has changed. Now that we have the<br>
separate osmo-bsc, we will need two layers of handover: intra-BSC and<br>
inter-BSC.<br>
<br>
Intra-BSC is a handover between two cells that are serviced by the same BSC,<br>
and the higher layers (MSC) should not even notice that anything has happened<br>
-- MSC has asked the BSC to service a call by BSSAP Assignment, and the BSC is<br>
free to choose and change around the lchans it assigns to that. That is the<br>
layer I'm currently dug into.<br>
<br>
Inter-BSC is a handover between cells that are serviced by two different BSCs.<br>
That seems to be the land your patch is improving. The MSC is involved and so<br>
is MNCC.<br>
<br>
(Both MSC and BSC levels will need their own DTAP cache, and they are by<br>
definition completely independent -- MSC caches the DTAP coming from MNCC<br>
during Inter-BSC handover, BSC caches DTAP from MSC during Intra-BSC handover.)<br>
<br>
Since your patch is applied onto openbsc.git, where all of BSC and MSC are<br>
still one osmo-nitb, I want to make sure that I sort your patch right. Do some<br>
of its semantics apply to osmo-bsc master, even if the code changed?<br>
<br>
The smaller patches are either already applied to osmo-bsc master, or I've<br>
submitted them on gerrit just now:<br>
<br>
 handover_decision: Add more log messages to get more information about HO causes in logs<br>
 handover_decision: Fix condition for power budget handover attempt<br>
 handover_logic: set correct link to bts for subscriber_connection in case of moving this connection to another bts<br>
<br>
Remaining are a small and *the* complex one:<br>
<br>
 transaction: Add new function trans_find_by_lchan<br>
 handover: Implement proper handover procedure handling at any stage of the call<br>
<br>
Here is the last one with inline questions, I hope they are not too stupid; or<br>
too long, it ended up being a lot to read. Thanks in advance for taking a look:<br>
<br>
<br>
> commit f7f4dc5e3b0dd61b8322946597147b<wbr>aef5d0464b<br>
> Author: Ivan Kluchnikov <<a href="mailto:kluchnikovi@gmail.com">kluchnikovi@gmail.com</a>><br>
> Date:   Wed Aug 23 18:09:50 2017 +0300<br>
><br>
>     handover: Implement proper handover procedure handling at any stage of the call<br>
><br>
>     Enhancements for each stage of handover procedure should be implemented in order to support handover at any stage of the call.<br>
>     For these purposes new in_handover state and ho_queue for call control messages was introduced for gsm_subscriber_connection.<br>
><br>
>     Stage 1: HO-Command is sent to MS<br>
>     gsm_subscriber_connection state should be changed to in_handover=1.<br>
>     In this state all transmission of signalling layer messages (except RR messages needed for handover procedure)<br>
>     should be suspended until resuming is indicated.<br>
>     All call control messages for connection received from network side should be buffered in ho_queue.<br>
>     All call control messages for connection received from MS side should be ignored.<br>
>     Channel mode modification procedures should be also suspended.<br>
><br>
>     Stage 2: HO-Detect is received from MS<br>
>     Audio path should be switched on network side.<br>
><br>
>     Stage 3-1: HO-Complete is received from MS<br>
>     Resumption procedure after successful handover should be performed:<br>
>      - gsm_subscriber_connection state should be changed to normal (in_handover=0).<br>
>      - all buffered call control messages (ho_queue) should be sent to MS on new lchan.<br>
>      - suspended channel mode modification procedures should be performed on new lchan.<br>
><br>
>     Stage 3-2: HO-Fail is received from MS<br>
>     Resumption procedure after failed handover should be performed:<br>
>      - gsm_subscriber_connection state should be changed to normal (in_handover=0).<br>
>      - all buffered call control messages (ho_queue) should be sent to MS on old lchan.<br>
>      - suspended channel mode modification procedures should be performed on old lchan.<br>
><br>
>     Stage 3-3: T3103 expired: Handover has failed without HO-Complete or HO-Fail<br>
>     Resumption procedure should not be performed in case of T3103 expired:<br>
>      - gsm_subscriber_connection state should be changed to normal (in_handover=0).<br>
>      - all buffered call control messages (ho_queue) should be cleaned without sending them to MS.<br>
>      - suspended channel mode modification procedures should not be performed.<br>
><br>
>     Change-Id: Icb9b5c35ef0c894af2ea762e539f1<wbr>a9216447fb7<br>
><br>
> diff --git a/openbsc/include/openbsc/bsc_<wbr>api.h b/openbsc/include/openbsc/bsc_<wbr>api.h<br>
> index 3a931199..baacbeda 100644<br>
> --- a/openbsc/include/openbsc/bsc_<wbr>api.h<br>
> +++ b/openbsc/include/openbsc/bsc_<wbr>api.h<br>
> @@ -51,5 +51,6 @@ int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,<br>
>  int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,<br>
>                unsigned int mi_len, uint8_t *mi, int chan_type);<br>
>  int gsm0808_clear(struct gsm_subscriber_connection *conn);<br>
> +int gsm0808_ho_clear(struct gsm_subscriber_connection *conn);<br>
><br>
>  #endif<br>
> diff --git a/openbsc/include/openbsc/gsm_<wbr>data.h b/openbsc/include/openbsc/gsm_<wbr>data.h<br>
> index ac573c49..542b2611 100644<br>
> --- a/openbsc/include/openbsc/gsm_<wbr>data.h<br>
> +++ b/openbsc/include/openbsc/gsm_<wbr>data.h<br>
> @@ -138,6 +138,8 @@ struct gsm_subscriber_connection {<br>
>       struct gsm_network *network;<br>
><br>
>       int in_release;<br>
> +     int in_handover;<br>
> +     struct llist_head ho_queue;<br>
>       struct gsm_lchan *lchan; /* BSC */<br>
>       struct gsm_lchan *ho_lchan; /* BSC */<br>
>       struct gsm_bts *bts; /* BSC */<br>
> diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c<br>
> index 8a4c85ff..71e82d03 100644<br>
> --- a/openbsc/src/libbsc/bsc_api.c<br>
> +++ b/openbsc/src/libbsc/bsc_api.c<br>
> @@ -253,11 +253,14 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(<wbr>struct gsm_lchan *lcha<br>
>       conn->bts = lchan->ts->trx->bts;<br>
>       lchan->conn = conn;<br>
>       llist_add_tail(&conn->entry, &net->subscr_conns);<br>
> +     INIT_LLIST_HEAD(&conn->ho_<wbr>queue);<br>
>       return conn;<br>
>  }<br>
><br>
>  void bsc_subscr_con_free(struct gsm_subscriber_connection *conn)<br>
>  {<br>
> +     struct msgb *msg;<br>
> +<br>
>       if (!conn)<br>
>               return;<br>
><br>
> @@ -283,6 +286,11 @@ void bsc_subscr_con_free(struct gsm_subscriber_connection *conn)<br>
>               conn->secondary_lchan->conn = NULL;<br>
>       }<br>
><br>
> +     while (!llist_empty(&conn->ho_queue)<wbr>) {<br>
> +             msg = msgb_dequeue(&conn->ho_queue);<br>
> +             msgb_free(msg);<br>
> +     }<br>
> +<br>
>       llist_del(&conn->entry);<br>
>       talloc_free(conn);<br>
>  }<br>
> @@ -747,6 +755,17 @@ int gsm0808_clear(struct gsm_subscriber_connection *conn)<br>
>       return 0;<br>
>  }<br>
><br>
> +/*<br>
> + * Release handover RF Channel.<br>
> + */<br>
> +int gsm0808_ho_clear(struct gsm_subscriber_connection *conn)<br>
> +{<br>
> +     if (conn->ho_lchan)<br>
> +             bsc_clear_handover(conn, 1);<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
>  static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id)<br>
>  {<br>
>       struct bsc_api *api;<br>
> diff --git a/openbsc/src/libbsc/handover_<wbr>logic.c b/openbsc/src/libbsc/handover_<wbr>logic.c<br>
> index af4e8013..b7085c34 100644<br>
> --- a/openbsc/src/libbsc/handover_<wbr>logic.c<br>
> +++ b/openbsc/src/libbsc/handover_<wbr>logic.c<br>
> @@ -186,10 +186,17 @@ static void ho_T3103_cb(void *_ho)<br>
>  {<br>
>       struct bsc_handover *ho = _ho;<br>
>       struct gsm_network *net = ho->new_lchan->ts->trx->bts-><wbr>network;<br>
> +     struct msgb *msg;<br>
><br>
>       DEBUGP(DHO, "HO T3103 expired\n");<br>
>       rate_ctr_inc(&net->bsc_ctrs-><wbr>ctr[BSC_CTR_HANDOVER_TIMEOUT])<wbr>;<br>
><br>
> +     ho->new_lchan->conn->in_<wbr>handover = 0;<br>
> +     while (!llist_empty(&ho->new_lchan-><wbr>conn->ho_queue)) {<br>
> +             msg = msgb_dequeue(&ho->new_lchan-><wbr>conn->ho_queue);<br>
> +             msgb_free(msg);<br>
> +     }<br>
> +<br>
<br>
(Your ho_queue seems to live in libbsc, while most of the patch seems to be<br>
concerned with libmsc. But nevermind, from jolly's patches I already have a<br>
similar queue in osmo-bsc, and we'll probably use yours for libmsc.)<br></blockquote><div><br></div><div><br></div><div>It's ok, as you wrote above, we should have a queue in osmo-bsc and in libmsc.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>       ho->new_lchan->conn->ho_lchan = NULL;<br>
>       ho->new_lchan->conn = NULL;<br>
>       lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);<br>
> @@ -214,6 +221,8 @@ static int ho_chan_activ_ack(struct gsm_lchan *new_lchan)<br>
><br>
>       gsm48_send_ho_cmd(ho->old_<wbr>lchan, new_lchan, 0, ho->ho_ref);<br>
><br>
> +     new_lchan->conn->in_handover = 1;<br>
> +<br>
<br>
In current osmo-bsc master, we already set conn->ho_lchan before sending out<br>
the chan activation request. I'd actually assume setting the flag only now,<br>
after the activ ack, is a bit too late?</blockquote><div><br></div><div>I set it right after gsm48_send_ho_cmd, because sending of HO CMD is the actual start of handover procedure (as I understand specs).<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>       /* start T3103.  We can continue either with T3103 expiration,<br>
>        * 04.08 HANDOVER COMPLETE or 04.08 HANDOVER FAIL */<br>
>       ho->T3103.cb = ho_T3103_cb;<br>
> @@ -221,7 +230,8 @@ static int ho_chan_activ_ack(struct gsm_lchan *new_lchan)<br>
>       osmo_timer_schedule(&ho-><wbr>T3103, 10, 0);<br>
><br>
>       /* create a RTP connection */<br>
> -     if (is_ipaccess_bts(new_lchan-><wbr>ts->trx->bts))<br>
> +     if (is_ipaccess_bts(new_lchan-><wbr>ts->trx->bts) &&<br>
> +                                     new_lchan->tch_mode != GSM48_CMODE_SIGN)<br>
>               rsl_ipacc_crcx(new_lchan);<br>
<br>
Please explain ... what case / behavior is this fixing?<br>
Do we ever see CMODE_SIGN handovers?<br>
Would we also need to check for GSM48_CMODE_DATA_*?<br></blockquote><div><br></div><div><div>Yes, handover can be initiated in any mode of lchan and we saw handovers for lchans in GSM48_CMODE_SIGN mode.</div><div>So I think we should be able to cover this case because I didn't find any mention in the specs that this case is prohibited for HO.</div><div>I don't know if HO is allowed for CSD (GSM48_CMODE_DATA_*), it should be checked.</div><div>But if it is prohibited for CSD, I think we should check and block it on the stage of bsc_handover_start or earlier.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> @@ -273,6 +283,11 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)<br>
>       if (is_e1_bts(new_lchan->conn-><wbr>bts))<br>
>               switch_trau_mux(ho->old_lchan, new_lchan);<br>
><br>
> +     if (ho->old_lchan->conn->mncc_<wbr>rtp_connect_pending) {<br>
> +             new_lchan->abis_ip.connect_<wbr>port = ho->old_lchan->abis_ip.<wbr>connect_port;<br>
> +             new_lchan->abis_ip.connect_ip = ho->old_lchan->abis_ip.<wbr>connect_ip;<br>
> +     }<br>
> +<br>
<br>
So if an RTP connect to MNCC is pending, we copy the old lchan's RTP port and<br>
IP? Which is this, the MNCC / call router side IP and port?<br></blockquote><div><br></div><div><div>Yes, Remote (MGW) IP address and port for RTP.</div><div>We set them in tch_rtp_connect function:</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">      </span>trans->conn->mncc_rtp_connect_pending = 1;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>if (trans->conn->in_handover) {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">               </span>lchan->abis_ip.connect_port = rtp->port;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">              </span>lchan->abis_ip.connect_ip = rtp->ip;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">          </span>return 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>}</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">   </span>return rsl_ipacc_mdcx(lchan, rtp->ip, rtp->port, 0);</div><div>  }</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Why not set this at the initiation of the HO already?<br></blockquote><div><br></div><div>We can't set this at the initiation of the HO because it is possible that we don't have port and IP of the remote part at the HO initiation, and we can get them during HO procedure (in "parallel" with HO procedure), as you can see in tch_rtp_connect function above.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> @@ -295,27 +310,9 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)<br>
>  static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)<br>
>  {<br>
>       struct gsm_network *net = old_lchan->ts->trx->bts-><wbr>network;<br>
> -     struct bsc_handover *ho;<br>
> -     struct gsm_lchan *new_lchan;<br>
> -<br>
> -     ho = bsc_ho_by_old_lchan(old_lchan)<wbr>;<br>
> -     if (!ho) {<br>
> -             LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");<br>
> -             return -ENODEV;<br>
> -     }<br>
><br>
>       rate_ctr_inc(&net->bsc_ctrs-><wbr>ctr[BSC_CTR_HANDOVER_FAILED]);<br>
><br>
> -     new_lchan = ho->new_lchan;<br>
> -<br>
> -     /* release the channel and forget about it */<br>
> -     ho->new_lchan->conn->ho_lchan = NULL;<br>
> -     ho->new_lchan->conn = NULL;<br>
> -     handover_free(ho);<br>
> -<br>
> -     lchan_release(new_lchan, 0, RSL_REL_LOCAL_END);<br>
> -<br>
> -<br>
<br>
I'm puzzled by this removal. No actions during ho_fail? Is this really<br>
intended, or just some rebase artifact?<br></blockquote><div><br></div><div><div>It was before the split of the code, so I moved it to openbsc/src/libmsc/gsm_04_08.c:</div><div>+static int ho_fail(struct gsm_lchan *old_lchan)<br></div><div> +{</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>struct gsm_trans *trans;</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">  </span>old_lchan->conn->in_handover = 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>trans = trans_find_by_lchan(old_lchan);</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>if (trans)</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">          </span>ho_resumption(old_lchan, trans);</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>else {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">              </span>LOGP(DHO, LOGL_ERROR, "%s HO fail, but no transaction for old_lchan.\n",</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                  </span>gsm_lchan_name(old_lchan));</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">         </span>ho_queue_clean(old_lchan->conn);</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>}</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>gsm0808_ho_clear(old_lchan->conn);</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>return 0;</div><div> +}</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>       return 0;<br>
>  }<br>
><br>
> diff --git a/openbsc/src/libmsc/gsm_04_<wbr>08.c b/openbsc/src/libmsc/gsm_04_<wbr>08.c<br>
> index e5402d0a..84338d72 100644<br>
> --- a/openbsc/src/libmsc/gsm_04_<wbr>08.c<br>
> +++ b/openbsc/src/libmsc/gsm_04_<wbr>08.c<br>
> @@ -147,6 +147,15 @@ static int gsm48_conn_sendmsg(struct msgb *msg, struct gsm_subscriber_connection<br>
>                               sign_link->trx->bts->nr,<br>
>                               sign_link->trx->nr, msg->lchan->ts->nr,<br>
>                               gh->proto_discr, gh->msg_type);<br>
> +<br>
> +             if (conn->in_handover) {<br>
> +                     msgb_enqueue(&conn->ho_queue, msg);<br>
> +                     DEBUGP(DCC, "(bts %d trx %d ts %d) Suspend message sending to MS, "<br>
> +                             "active HO procedure.\n",<br>
> +                             sign_link->trx->bts->nr,<br>
> +                             sign_link->trx->nr, msg->lchan->ts->nr);<br>
> +                     return 0;<br>
> +             }<br>
<br>
(here DTAP handled in libmsc ends up in the ho_queue that otherwise seems to<br>
live in libbsc ... as I said above this queue will probably move to libmsc<br>
altogether to become part of osmo-msc master.)<br></blockquote><div> </div><div>Ok.</div><div><br></div><div> >       }</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
><br>
>       return gsm0808_submit_dtap(conn, msg, 0, 0);<br>
> @@ -1749,11 +1758,8 @@ static int switch_for_handover(struct gsm_lchan *old_lchan,<br>
>       struct rtp_socket *old_rs, *new_rs, *other_rs;<br>
><br>
>       /* Ask the new socket to send to the already known port. */<br>
> -     if (new_lchan->conn->mncc_rtp_<wbr>bridge) {<br>
> -             LOGP(DHO, LOGL_DEBUG, "Forwarding RTP\n");<br>
> -             rsl_ipacc_mdcx(new_lchan,<br>
> -                                     old_lchan->abis_ip.connect_ip,<br>
> -                                     old_lchan->abis_ip.connect_<wbr>port, 0);<br>
> +     if (new_lchan->ts->trx->bts-><wbr>network->mncc_state) {<br>
> +             /* Audio path should be switched after receiving ho detect message.*/<br>
>               return 0;<br>
>       }<br>
<br>
I notice that in the current head, the entire switch_for_handover() has been<br>
dropped; it was doing libbsc lchan stuff from within libmsc. Hence we must have<br>
added similar logic in osmo-bsc.git and completely dropped this.<br>
<br></blockquote><div><br></div><div><div>Yes, it is correct.</div></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I think the commit re-implementing handover in osmo-bsc is<br>
<a href="http://git.osmocom.org/osmo-bsc/commit/?id=39c609b7c924524172ad311bdf89f92b7ccf175a" rel="noreferrer">http://git.osmocom.org/osmo-<wbr>bsc/commit/?id=<wbr>39c609b7c924524172ad311bdf89f9<wbr>2b7ccf175a</a><br>
<br>
It appears that lchan->abis_ip.connect_ip and connect_port aren't used at all<br>
in osmo-bsc master, but are still present in the struct. I'll ask others about<br>
that.<br>
<br>
In any case, the code base has changed substantially, and this patch hunk no<br>
longer applies at all.<br>
<br>
Am I interpreting this hunk correctly: it moves the ipacc_mdcx to tell the new<br>
lchan about its RTP peer to a later stage?<br></blockquote><div><br></div><div><div><div>Yes, we call rsl_ipacc_mdcx function after receiving ho detect message.</div><div>See ho_detect function in openbsc/src/libmsc/gsm_04_08.c:</div></div><div>+static int ho_detect(struct gsm_lchan *new_lchan)</div><div> +{</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>struct gsm_trans *trans;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>struct gsm_lchan *old_lchan;</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>trans = trans_find_by_lchan(new_lchan);</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>if (!trans) {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">               </span>LOGP(DHO, LOGL_ERROR, "%s HO detected, but no transaction for new_lchan"</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                  </span>" with enabled tch_recv.\n",</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                      </span>gsm_lchan_name(new_lchan));</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">         </span>return 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>}</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>if (!new_lchan->conn->mncc_rtp_bridge) {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">              </span>LOGP(DHO, LOGL_ERROR, "%s HO detected, but connection not in mncc_rtp_bridge mode.\n",</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                    </span>gsm_lchan_name(new_lchan));</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">         </span>return 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>}</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>old_lchan = bsc_handover_pending(new_lchan);</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>if (!old_lchan) {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">           </span>LOGP(DHO, LOGL_ERROR, "%s HO detected, but no old_lchan for handover.\n",</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                 </span>gsm_lchan_name(new_lchan));</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">         </span>return 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>}</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>LOGP(DHO, LOGL_DEBUG, "HO detected, forwarding RTP\n");</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>rsl_ipacc_mdcx(new_lchan,</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                           </span>old_lchan->abis_ip.connect_ip,</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                           </span>old_lchan->abis_ip.connect_port, 0);</div><div> +</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>mncc_recv_rtp_modify(new_lchan, trans->callref);</div><div> +</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">       </span>return 0;</div><div>  }</div></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
In current osmo-bsc master, it seems that this ipacc_mdcx happens as soon as<br>
the ipacc_crcx is complete, seen in osmo-bsc/src/osmo-bsc/osmo_<wbr>bsc_audio.c in<br>
handle_abisip_signal(), always using the IP:port the MSC sent us.<br><br></blockquote><div><br></div><div>I am not sure that it is the proper place for calling rsl_ipacc_mdcx in case of handover, as I understand spec, we should switch media path only after receiving ho detect message, but it should be checked.<br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
><br>
> @@ -1821,8 +1827,10 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,<br>
>       if (subsys != SS_ABISIP)<br>
>               return 0;<br>
><br>
> +     net = lchan->ts->trx->bts->network;<br>
> +<br>
>       /* RTP bridge handling */<br>
> -     if (lchan->conn && lchan->conn->mncc_rtp_bridge)<br>
> +     if (lchan->conn && net->mncc_state)<br>
>               return tch_rtp_signal(lchan, signal);<br>
<br>
What are the semantics here? It seems odd to move from a check of a<br>
conn-specific state (conn->mncc_rtp_bridge) to a check of a global value<br>
(net->mncc_state).<br></blockquote><div><br></div><div>Hm, yes, it seems odd for this case.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
In any case, this is MNCC related and should not impact Intra-BSC handover,<br>
right?<br></blockquote><div><br></div><div>Yes, it is MNCC related only.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
><br>
>       /* in case we use direct BTS-to-BTS RTP */<br>
> @@ -1851,7 +1859,6 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal,<br>
><br>
>               /* check if any transactions on this lchan still have<br>
>                * a tch_recv_mncc request pending */<br>
> -             net = lchan->ts->trx->bts->network;<br>
>               llist_for_each_entry(trans, &net->trans_list, entry) {<br>
>                       if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) {<br>
>                               DEBUGP(DCC, "pending tch_recv_mncc request\n");<br>
> @@ -2017,6 +2024,13 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)<br>
>          switch (bts->type) {<br>
>          case GSM_BTS_TYPE_NANOBTS:<br>
>          case GSM_BTS_TYPE_OSMO_SYSMO:<br>
>               if (ipacc_rtp_direct) {<br>
>                       LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n");<br>
>                       return -EINVAL;<br>
>               }<br>
> +             /* RTP bridge handling */<br>
> +             if (lchan->conn && net->mncc_state) {<br>
> +                     return 0;<br>
> +             }<br>
<br>
If we have a conn and using external MNCC, don't continue at all? I'm not<br>
following, would be nice if the comment explained why we need to drop out here.<br>
<br>
(added some more code context manually)<br></blockquote><div><br></div><div><br></div><div><div>Yes, in this case, we set trans->tch_recv only in the code above.</div><div>In case of mncc bridge mode, audio socket creating and connecting are handled in tch_rtp_create and tch_rtp_connect functions (handlers of MNCC_RTP_CREATE and MNCC_RTP_CONNECT messages). </div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
>               /* In case, we don't have a RTP socket to the BTS yet, the BTS<br>
>               * will not be connected to our RTP proxy and the socket will<br>
>               * not be assigned to the application interface. This method<br>
>               * will be called again, once the audio socket is created and<br>
>               * connected. */<br>
>               if (!lchan->abis_ip.rtp_socket) {<br>
>                       DEBUGP(DCC, "queue tch_recv_mncc request (%d)\n", enable);<br>
>                       return 0;<br>
>               }<br>
>               if (enable) {<br>
>                       /* connect the TCH's to our RTP proxy */<br>
>                       rc = rsl_ipacc_mdcx_to_rtpsock(<wbr>lchan);<br>
>                       if (rc < 0)<br>
>                               return rc;<br>
>                       /* assign socket to application interface */<br>
>                       rtp_socket_upstream(lchan-><wbr>abis_ip.rtp_socket,<br>
>                               net, callref);<br>
>               } else<br>
>                       rtp_socket_upstream(lchan-><wbr>abis_ip.rtp_socket,<br>
>                               net, 0);<br>
>               break;<br>
><br>
<br>
<br>
<br>
> @@ -3325,6 +3339,41 @@ static void mncc_recv_rtp_err(struct gsm_network *net, uint32_t callref, int cmd<br>
>       return mncc_recv_rtp(net, callref, cmd, 0, 0, 0, 0);<br>
>  }<br>
><br>
> +static void mncc_recv_rtp_modify(struct gsm_lchan *lchan, uint32_t callref)<br>
<br>
This is to tell the call router that the payload type has changed, right?</blockquote><div><br></div><div>Yes.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  I've<br>
asked in the redmine about whether/how we'd convey an RTP payload change to the<br>
MNCC in case of an Intra-BSC handover...<br>
<br>
<a href="https://osmocom.org/issues/1606#note-45" rel="noreferrer">https://osmocom.org/issues/<wbr>1606#note-45</a><br>
<br></blockquote><div><br></div><div>Ok, I will check this issue.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +{<br>
> +     int msg_type;<br>
> +     struct gsm_network *net = lchan->ts->trx->bts->network;<br>
> +<br>
> +     LOGP(DMNCC, LOGL_NOTICE, "%s sending pending RTP modify ind.\n",<br>
> +             gsm_lchan_name(lchan));<br>
> +<br>
> +     switch (lchan->abis_ip.rtp_payload) {<br>
> +     case RTP_PT_GSM_FULL:<br>
> +             msg_type = GSM_TCHF_FRAME;<br>
> +             break;<br>
> +     case RTP_PT_GSM_EFR:<br>
> +             msg_type = GSM_TCHF_FRAME_EFR;<br>
> +             break;<br>
> +     case RTP_PT_GSM_HALF:<br>
> +             msg_type = GSM_TCHH_FRAME;<br>
> +             break;<br>
> +     case RTP_PT_AMR:<br>
> +             msg_type = GSM_TCH_FRAME_AMR;<br>
> +             break;<br>
> +     default:<br>
> +             LOGP(DMNCC, LOGL_ERROR, "%s unknown payload type %d\n",<br>
> +                     gsm_lchan_name(lchan), lchan->abis_ip.rtp_payload);<br>
> +             msg_type = 0;<br>
> +             break;<br>
> +     }<br>
> +<br>
> +     mncc_recv_rtp(net, callref, MNCC_RTP_MODIFY,<br>
> +                     lchan->abis_ip.bound_ip,<br>
> +                     lchan->abis_ip.bound_port,<br>
> +                     lchan->abis_ip.rtp_payload,<br>
> +                     msg_type);<br>
> +}<br>
> +<br>
>  static int tch_rtp_create(struct gsm_network *net, uint32_t callref)<br>
>  {<br>
>       struct gsm_bts *bts;<br>
> @@ -3374,6 +3423,9 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref)<br>
>               LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n",<br>
>                    get_value_string(gsm48_chan_<wbr>mode_names, m),<br>
>                    get_value_string(gsm_chan_t_<wbr>names, lchan->type));<br>
> +             if (trans->conn->in_handover) {<br>
> +                     return 0;<br>
> +             }<br>
<br>
Am I reading right: if we're doing handover, the MSC shouldn't sent another<br>
BSSAP Assignment to the BSC; instead, the BSC level figures out another lchan<br>
and done ... ?<br></blockquote><div><br></div><div><div>I will add some context:</div><div><br></div><div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">    </span>if (lchan->tch_mode == GSM48_CMODE_SIGN) {</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">                </span>trans->conn->mncc_rtp_create_pending = 1;</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">              </span>m = mncc_codec_for_mode(lchan->type);</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">            </span>LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n",</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">           </span>     get_value_string(gsm48_chan_mode_names, m),</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">          </span>     get_value_string(gsm_chan_t_names, lchan->type));</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">         </span>if (trans->conn->in_handover) {</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">                       </span>return 0;</div><div> +<span class="gmail-Apple-tab-span" style="white-space:pre">           </span>}</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">           </span>return gsm0808_assign_req(trans->conn, m,</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre">                                </span>lchan->type != GSM_LCHAN_TCH_H);</div><div>  <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>}</div></div><div><br></div><div>As I understand, MSC can send sent another BSSAP Assignment to the BSC, but it doesn't make sense to send it to MS during a handover procedure, so it should be cached and send after handover.</div><div>In our implementation, we call gsm0808_assign_req for new lchan in the code below, when HO is completed and mncc_rtp_create_pending = 1.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>               return gsm0808_assign_req(trans-><wbr>conn, m,<br>
>                               lchan->type != GSM_LCHAN_TCH_H);<br>
>       }<br>
> @@ -3420,23 +3472,21 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg)<br>
>        * same package!<br>
>        */<br>
>       trans->conn->mncc_rtp_connect_<wbr>pending = 1;<br>
> +     if (trans->conn->in_handover) {<br>
> +             lchan->abis_ip.connect_port = rtp->port;<br>
> +             lchan->abis_ip.connect_ip = rtp->ip;<br>
> +             return 0;<br>
> +     }<br>
>       return rsl_ipacc_mdcx(lchan, rtp->ip, rtp->port, 0);<br>
<br>
We're not telling the BTS about the call router's IP:port anymore?<br>
Please explain...<br>
<br></blockquote><div><br></div><div><div>The same idea as above, it doesn't make sense to send it to old lchan during a handover procedure, so it should be cached and send after handover.</div><div>In our implementation we call rsl_ipacc_mdcx for new lchan in the code below, when HO is completed and mncc_rtp_connect_pending = 1.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>  }<br>
><br>
>  static int tch_rtp_signal(struct gsm_lchan *lchan, int signal)<br>
>  {<br>
>       struct gsm_network *net;<br>
> -     struct gsm_trans *tmp, *trans = NULL;<br>
> +     struct gsm_trans *trans;<br>
><br>
>       net = lchan->ts->trx->bts->network;<br>
> -     llist_for_each_entry(tmp, &net->trans_list, entry) {<br>
> -             if (!tmp->conn)<br>
> -                     continue;<br>
> -             if (tmp->conn->lchan != lchan && tmp->conn->ho_lchan != lchan)<br>
> -                     continue;<br>
> -             trans = tmp;<br>
> -             break;<br>
> -     }<br>
> +     trans = trans_find_by_lchan(lchan);<br>
><br>
>       if (!trans) {<br>
>               LOGP(DMNCC, LOGL_ERROR, "%s IPA abis signal but no transaction.\n",<br>
> @@ -3459,7 +3509,7 @@ static int tch_rtp_signal(struct gsm_lchan *lchan, int signal)<br>
>               maybe_switch_for_handover(<wbr>lchan);<br>
>               break;<br>
>       case S_ABISIP_MDCX_ACK:<br>
> -             if (lchan->conn->mncc_rtp_<wbr>connect_pending) {<br>
> +             if (lchan->conn->mncc_rtp_<wbr>connect_pending && !lchan->conn->in_handover) {<br>
<br>
if we're in handover, we don't need to tell MNCC that RTP got connected,<br>
because that already happened when the call got established initially?<br>
So mncc_rtp_connect_pending has a second meaning during handover?<br></blockquote><div><br></div><div>Yes, as I wrote above, mncc_rtp_connect_pending during handover means that we cached call of rsl_ipacc_mdcx function and should call it after handover.  </div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>                       lchan->conn->mncc_rtp_connect_<wbr>pending = 0;<br>
>                       LOGP(DMNCC, LOGL_NOTICE, "%s sending pending RTP connect ind.\n",<br>
>                               gsm_lchan_name(lchan));<br>
>                       mncc_recv_rtp_sock(net, trans, MNCC_RTP_CONNECT);<br>
>               }<br>
>               break;<br>
<br>
> @@ -3471,6 +3521,134 @@ static int tch_rtp_signal(struct gsm_lchan *lchan, int signal)<br>
>       return 0;<br>
>  }<br>
><br>
> +static void ho_queue_clean(struct gsm_subscriber_connection *conn)<br>
> +{<br>
> +     struct msgb *msg;<br>
> +     while (!llist_empty(&conn->ho_queue)<wbr>) {<br>
> +             msg = msgb_dequeue(&conn->ho_queue);<br>
> +             msgb_free(msg);<br>
> +     }<br>
> +}<br>
> +<br>
> +static void ho_resumption(struct gsm_lchan *lchan, struct gsm_trans *trans)<br>
> +{<br>
> +     struct msgb *msg;<br>
> +     enum gsm48_chan_mode m;<br>
> +<br>
> +     while (!llist_empty(&lchan->conn-><wbr>ho_queue)) {<br>
> +             msg = msgb_dequeue(&lchan->conn->ho_<wbr>queue);<br>
> +             gsm48_conn_sendmsg(msg, lchan->conn, trans);<br>
> +     }<br>
> +<br>
> +     if (trans->conn->mncc_rtp_create_<wbr>pending &&<br>
> +                                     lchan->tch_mode == GSM48_CMODE_SIGN) {<br>
> +       m = mncc_codec_for_mode(lchan-><wbr>type);<br>
> +       gsm0808_assign_req(lchan-><wbr>conn, m, lchan->type != GSM_LCHAN_TCH_H);<br>
<br>
Wait, now we *do* send a BSSAP Assignment after all?<br>
(excuse if I'm being noob, I'm still finding my way through handover in general)<br></blockquote><div><br></div><div>Yes, at this stage we have "cached" BSSAP Assignment (because of mncc_rtp_create_pending=1).</div><div>HO was completed, so we send "cached" BSSAP Assignment for the new lchan.</div><div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
shouldn't we rather dequeue the cached DTAP after this instead of before?<br></blockquote><div> </div><div>It is a good question because for my tests it was ok, but I am not sure the current version of the code covered all use cases, so it is better to check.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +  }<br>
> +<br>
> +     if (trans->conn->mncc_rtp_<wbr>connect_pending) {<br>
> +             rsl_ipacc_mdcx(lchan, lchan->abis_ip.connect_ip, lchan->abis_ip.connect_port, 0);<br>
> +     }<br>
> +}<br>
> +<br>
> +static int ho_complete(struct gsm_lchan *new_lchan)<br>
> +{<br>
> +     struct gsm_trans *trans;<br>
> +<br>
> +     new_lchan->conn->in_handover = 0;<br>
> +     trans = trans_find_by_lchan(new_lchan)<wbr>;<br>
> +     if (!trans) {<br>
> +             LOGP(DHO, LOGL_ERROR, "%s HO detected, but no transaction for new_lchan.\n",<br>
> +                     gsm_lchan_name(new_lchan));<br>
> +             ho_queue_clean(new_lchan-><wbr>conn);<br>
> +             return 0;<br>
> +     }<br>
> +<br>
> +     ho_resumption(new_lchan, trans);<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +static int ho_fail(struct gsm_lchan *old_lchan)<br>
> +{<br>
> +     struct gsm_trans *trans;<br>
> +<br>
> +     old_lchan->conn->in_handover = 0;<br>
> +     trans = trans_find_by_lchan(old_lchan)<wbr>;<br>
> +     if (trans)<br>
> +             ho_resumption(old_lchan, trans);<br>
> +     else {<br>
> +             LOGP(DHO, LOGL_ERROR, "%s HO fail, but no transaction for old_lchan.\n",<br>
> +                     gsm_lchan_name(old_lchan));<br>
> +             ho_queue_clean(old_lchan-><wbr>conn);<br>
> +     }<br>
> +<br>
> +     gsm0808_ho_clear(old_lchan-><wbr>conn);<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +static int ho_detect(struct gsm_lchan *new_lchan)<br>
> +{<br>
> +     struct gsm_trans *trans;<br>
> +     struct gsm_lchan *old_lchan;<br>
> +<br>
> +     trans = trans_find_by_lchan(new_lchan)<wbr>;<br>
> +<br>
> +     if (!trans) {<br>
> +             LOGP(DHO, LOGL_ERROR, "%s HO detected, but no transaction for new_lchan"<br>
> +                     " with enabled tch_recv.\n",<br>
> +                     gsm_lchan_name(new_lchan));<br>
> +             return 0;<br>
> +     }<br>
> +<br>
> +     if (!new_lchan->conn->mncc_rtp_<wbr>bridge) {<br>
> +             LOGP(DHO, LOGL_ERROR, "%s HO detected, but connection not in mncc_rtp_bridge mode.\n",<br>
> +                     gsm_lchan_name(new_lchan));<br>
> +             return 0;<br>
> +     }<br>
> +<br>
> +     old_lchan = bsc_handover_pending(new_<wbr>lchan);<br>
> +     if (!old_lchan) {<br>
> +             LOGP(DHO, LOGL_ERROR, "%s HO detected, but no old_lchan for handover.\n",<br>
> +                     gsm_lchan_name(new_lchan));<br>
> +             return 0;<br>
> +     }<br>
> +<br>
> +     LOGP(DHO, LOGL_DEBUG, "HO detected, forwarding RTP\n");<br>
> +     rsl_ipacc_mdcx(new_lchan,<br>
> +                             old_lchan->abis_ip.connect_ip,<br>
> +                             old_lchan->abis_ip.connect_<wbr>port, 0);<br>
> +<br>
> +     mncc_recv_rtp_modify(new_<wbr>lchan, trans->callref);<br>
> +<br>
> +     return 0;<br>
> +}<br>
> +<br>
> +/* some other part of the code sends us a signal */<br>
> +static int handle_lchan_signal(unsigned int subsys, unsigned int signal,<br>
> +                              void *handler_data, void *signal_data)<br>
> +{<br>
> +     struct lchan_signal_data *lchan_data;<br>
> +     struct gsm_lchan *lchan;<br>
> +<br>
> +     lchan_data = signal_data;<br>
> +     switch (subsys) {<br>
> +     case SS_LCHAN:<br>
> +             lchan = lchan_data->lchan;<br>
> +             if (!lchan->conn)<br>
> +                     return 0;<br>
> +             switch (signal) {<br>
> +             case S_LCHAN_HANDOVER_DETECT:<br>
> +               return ho_detect(lchan);<br>
> +             case S_LCHAN_HANDOVER_COMPL:<br>
> +               return ho_complete(lchan);<br>
> +             case S_LCHAN_HANDOVER_FAIL:<br>
> +                     return ho_fail(lchan);<br>
> +             }<br>
> +             break;<br>
> +     }<br>
> +<br>
> +     return 0;<br>
> +}<br>
><br>
>  static struct downstate {<br>
>       uint32_t        states;<br>
> @@ -3853,6 +4031,11 @@ static int gsm0408_rcv_cc(struct gsm_subscriber_connection *conn, struct msgb *m<br>
>               gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0,<br>
>               gsm48_cc_state_name(trans?(<wbr>trans->cc.state):0));<br>
><br>
> +     if (conn->in_handover) {<br>
> +             DEBUGP(DCC, "Message unhandled, handover procedure.\n");<br>
> +             return 0;<br>
> +     }<br>
> +<br>
<br>
If in handover, drop all CC on the floor?<br>
<br>
How about a call release, i.e. I hang up while I'm coincidentally being<br>
handovered?<br>
<br></blockquote><div><br></div><div>Yes, the same issue, it worked ok for my tests, but we should test and check all cases.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
>       /* Create transaction */<br>
>       if (!trans) {<br>
>               DEBUGP(DCC, "Unknown transaction ID %x, "<br>
><br>
><br>
><br>
<br>
<br>
Thanks again!<br>
<span class="gmail-HOEnZb"><font color="#888888"><br>
~N<br>
</font></span></blockquote></div><br></div></div>