From f51f916e1cbaf5fae1ca10d18db84231fb1a4fdf Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 9 Nov 2023 13:19:34 +0100 Subject: [PATCH] LAPDm: Add an extra queue for UI frames The extra queue is used to transmit the UI frame only when there is no frame in the regular TX queue. This allows to give LAPD frames prioity over UI frame. Related: OS#4074 Change-Id: I00c8ee73be8b7c564a4dee3fca3e893484f567da --- TODO-RELEASE | 1 + include/osmocom/gsm/lapdm.h | 1 + src/gsm/lapdm.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/TODO-RELEASE b/TODO-RELEASE index 226450b06..fa7bc57bc 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -11,3 +11,4 @@ core ADD osmo_sock_multiaddr_{add,del}_local_addr() core ADD gsmtap_inst_fd2() core, DEPRECATE gsmtap_inst_fd() isdn ABI change add states and flags for external T200 handling gsm ABI change add T200 timer states to lapdm_datalink +gsm ABI change add UI queue to struct lapdm_datalink diff --git a/include/osmocom/gsm/lapdm.h b/include/osmocom/gsm/lapdm.h index db6668074..08b808c03 100644 --- a/include/osmocom/gsm/lapdm.h +++ b/include/osmocom/gsm/lapdm.h @@ -34,6 +34,7 @@ struct lapdm_datalink { struct lapdm_entity *entity; /*!< LAPDm entity we are part of */ + struct llist_head tx_ui_queue; /*!< UI frames to L1 */ uint32_t t200_fn; /*!< T200 timer in frames */ uint32_t t200_timeout; /*!< T200 timeout frame number */ }; diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c index d60931719..28644c28c 100644 --- a/src/gsm/lapdm.c +++ b/src/gsm/lapdm.c @@ -200,6 +200,7 @@ void lapdm_entity_init3(struct lapdm_entity *le, enum lapdm_mode mode, lapdm_dl_init(&le->datalink[i], le, (t200_ms) ? t200_ms[i] : 0, n200, name); } else lapdm_dl_init(&le->datalink[i], le, (t200_ms) ? t200_ms[i] : 0, n200, NULL); + INIT_LLIST_HEAD(&le->datalink[i].tx_ui_queue); } lapdm_entity_set_mode(le, mode); @@ -296,6 +297,7 @@ void lapdm_entity_exit(struct lapdm_entity *le) for (i = 0; i < ARRAY_SIZE(le->datalink); i++) { dl = &le->datalink[i]; lapd_dl_exit(&dl->dl); + msgb_queue_free(&dl->tx_ui_queue); } } @@ -390,6 +392,33 @@ static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg, return le->l1_prim_cb(&pp.oph, le->l1_ctx); } +static int tx_ph_data_enqueue_ui(struct lapdm_datalink *dl, struct msgb *msg, + uint8_t chan_nr, uint8_t link_id, uint8_t pad) +{ + struct lapdm_entity *le = dl->entity; + struct osmo_phsap_prim pp; + + /* if there is a pending message, queue it */ + if (le->tx_pending || le->flags & LAPDM_ENT_F_POLLING_ONLY) { + *msgb_push(msg, 1) = pad; + *msgb_push(msg, 1) = link_id; + *msgb_push(msg, 1) = chan_nr; + msgb_enqueue(&dl->tx_ui_queue, msg); + return 0; + } + + osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA, + PRIM_OP_REQUEST, msg); + pp.u.data.chan_nr = chan_nr; + pp.u.data.link_id = link_id; + + /* send the frame now */ + le->tx_pending = 0; /* disabled flow control */ + lapdm_pad_msgb(msg, pad); + + return le->l1_prim_cb(&pp.oph, le->l1_ctx); +} + /* Get transmit frame from queue, if any. In polling mode, indicate RTS to LAPD and start T200, if pending. */ static struct msgb *tx_dequeue_msgb(struct lapdm_datalink *dl, uint32_t fn) { @@ -420,6 +449,11 @@ static struct msgb *tx_dequeue_msgb(struct lapdm_datalink *dl, uint32_t fn) msg = msgb_dequeue(&dl->dl.tx_queue); if (msg) LOGDL(&dl->dl, LOGL_INFO, "Sending frame from TX queue. (FN %"PRIu32")\n", fn); + else { + msg = msgb_dequeue(&dl->tx_ui_queue); + if (msg) + LOGDL(&dl->dl, LOGL_INFO, "Sending UI frame from TX queue. (FN %"PRIu32")\n", fn); + } return msg; } @@ -1183,7 +1217,7 @@ static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl) } /* Tramsmit */ - return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, 23); + return tx_ph_data_enqueue_ui(dl, msg, chan_nr, link_id, 23); } /* L3 requests transfer of acknowledged information */ @@ -1580,6 +1614,7 @@ void lapdm_entity_reset(struct lapdm_entity *le) for (i = 0; i < ARRAY_SIZE(le->datalink); i++) { dl = &le->datalink[i]; lapd_dl_reset(&dl->dl); + msgb_queue_free(&dl->tx_ui_queue); } }