diff options
author | Daniel Willmann <dwillmann@sysmocom.de> | 2014-03-20 19:24:48 +0100 |
---|---|---|
committer | Daniel Willmann <daniel@totalueberwachung.de> | 2014-03-26 18:11:07 +0100 |
commit | 3dc4e16786d1e5723e76ad7c70ad54134957f9e5 (patch) | |
tree | c8a9609da0fff4967574b1d7af375d58a65f4788 /src/gsm/lapdm.c | |
parent | 09129352f99a90a784912ae3c8ff442268a35480 (diff) |
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.
Diffstat (limited to 'src/gsm/lapdm.c')
-rw-r--r-- | src/gsm/lapdm.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c index 4edae633..698f8502 100644 --- a/src/gsm/lapdm.c +++ b/src/gsm/lapdm.c @@ -114,6 +114,7 @@ enum lapdm_format { 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 @@ static void lapdm_dl_init(struct lapdm_datalink *dl, 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 @@ static int lapdm_send_ph_data_req(struct lapd_msg_ctx *lctx, struct msgb *msg) 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) |