gsm/lapdm: Prevent LAPD tx_queue from filling up in polling mode
If LAPDm receives an I-Frame while there already is an I-Frame in the
tx_queue the code generates an additional RR (to acknowledge the
received I-Frame). Instead, N(R) of the I-Frame in the tx_queue should
be updated to ACK the data.
diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c
index 4edae63..698f850 100644
--- a/src/gsm/lapdm.c
+++ b/src/gsm/lapdm.c
@@ -114,6 +114,7 @@
static int lapdm_send_ph_data_req(struct lapd_msg_ctx *lctx, struct msgb *msg);
static int send_rslms_dlsap(struct osmo_dlsap_prim *dp,
struct lapd_msg_ctx *lctx);
+static int update_pending_frames(struct lapd_msg_ctx *lctx);
static void lapdm_dl_init(struct lapdm_datalink *dl,
struct lapdm_entity *entity, int t200)
@@ -124,6 +125,7 @@
dl->dl.reestablish = 0; /* GSM uses no reestablish */
dl->dl.send_ph_data_req = lapdm_send_ph_data_req;
dl->dl.send_dlsap = send_rslms_dlsap;
+ dl->dl.update_pending_frames = update_pending_frames;
dl->dl.n200_est_rel = N200_EST_REL;
dl->dl.n200 = N200;
dl->dl.t203_sec = 0; dl->dl.t203_usec = 0;
@@ -488,6 +490,25 @@
23);
}
+static int update_pending_frames(struct lapd_msg_ctx *lctx)
+{
+ struct lapd_datalink *dl = lctx->dl;
+ struct msgb *msg;
+ int rc = -1;
+
+ llist_for_each_entry(msg, &dl->tx_queue, list) {
+ if (LAPDm_CTRL_is_I(msg->l2h[1])) {
+ msg->l2h[1] = LAPDm_CTRL_I(dl->v_recv, LAPDm_CTRL_I_Ns(msg->l2h[1]),
+ LAPDm_CTRL_PF_BIT(msg->l2h[1]));
+ rc = 0;
+ } else if (LAPDm_CTRL_is_S(msg->l2h[1])) {
+ LOGP(DLLAPD, LOGL_ERROR, "Supervisory frame in queue, this shouldn't happen\n");
+ }
+ }
+
+ return rc;
+}
+
/* input into layer2 (from layer 1) */
static int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le,
uint8_t chan_nr, uint8_t link_id)