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
This commit is contained in:
Andreas Eversberg 2023-11-09 13:19:34 +01:00 committed by laforge
parent 2d7119d85b
commit f51f916e1c
3 changed files with 38 additions and 1 deletions

View File

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

View File

@ -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 */
};

View File

@ -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);
}
}