fairwaves HO patches

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.co
Sun Jan 21 20:47:18 UTC 2018


Hi 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>


More information about the OpenBSC mailing list