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