From 3dc4e16786d1e5723e76ad7c70ad54134957f9e5 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 20 Mar 2014 19:24:48 +0100 Subject: 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. --- TODO-RELEASE | 2 ++ include/osmocom/gsm/lapd_core.h | 1 + src/gsm/lapd_core.c | 6 ++++++ src/gsm/lapdm.c | 21 +++++++++++++++++++++ tests/lapd/lapd_test.c | 12 ++++-------- tests/lapd/lapd_test.ok | 14 +++++--------- 6 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 TODO-RELEASE diff --git a/TODO-RELEASE b/TODO-RELEASE new file mode 100644 index 00000000..2a1f9788 --- /dev/null +++ b/TODO-RELEASE @@ -0,0 +1,2 @@ +#library what description / commit summary line +libosmogsm abi-change Prevent LAPD tx_queue from filling up in polling mode diff --git a/include/osmocom/gsm/lapd_core.h b/include/osmocom/gsm/lapd_core.h index c2fdc622..f88fb112 100644 --- a/include/osmocom/gsm/lapd_core.h +++ b/include/osmocom/gsm/lapd_core.h @@ -125,6 +125,7 @@ struct lapd_datalink { int (*send_dlsap)(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); int (*send_ph_data_req)(struct lapd_msg_ctx *lctx, struct msgb *msg); + int (*update_pending_frames)(struct lapd_msg_ctx *lctx); struct { /*! \brief filled-in once we set the lapd_mode above */ struct lapd_cr_ent loc2rem; diff --git a/src/gsm/lapd_core.c b/src/gsm/lapd_core.c index ef1d22a7..8c5fe9c6 100644 --- a/src/gsm/lapd_core.c +++ b/src/gsm/lapd_core.c @@ -1607,6 +1607,12 @@ static int lapd_rx_i(struct msgb *msg, struct lapd_msg_ctx *lctx) if (!dl->own_busy) { /* NOTE: V(R) is already set above */ rc = lapd_send_i(lctx, __LINE__); + + /* if update_pending_iframe returns 0 it updated + * the lapd header of an iframe in the tx queue */ + if (rc && dl->update_pending_frames) + rc = dl->update_pending_frames(lctx); + if (rc) { LOGP(DLLAPD, LOGL_INFO, "we are not busy and " "have no pending data, send RR\n"); 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) diff --git a/tests/lapd/lapd_test.c b/tests/lapd/lapd_test.c index c8bb394d..18ea1dc3 100644 --- a/tests/lapd/lapd_test.c +++ b/tests/lapd/lapd_test.c @@ -621,17 +621,13 @@ const uint8_t gprs_susp[] = { 0xd2, 0x6f, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x00, 0x02 }; -const uint8_t gprs_susp_ack[] = { - 0x01, 0x41, 0x01 -}; - const uint8_t cipher_cmd[] = { 0x06, 0x35, 0x01 }; -/* The cipher command we send to the MS */ +/* The cipher command we send to the MS after updating our N(R) */ const uint8_t cipher_cmd_out[] = { - 0x03, 0x20, 0x0d, 0x06, 0x35, 0x01 + 0x03, 0x40, 0x0d, 0x06, 0x35, 0x01 }; uint8_t cipher_compl[] = { @@ -730,7 +726,7 @@ static void test_lapdm_desync() rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH"); CHECK_RC(rc); - OSMO_ASSERT(memcmp(pp.oph.msg->l2h, gprs_susp_ack, ARRAY_SIZE(gprs_susp_ack)) == 0); + OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cipher_compl_ack, ARRAY_SIZE(cipher_compl_ack)) == 0); printf("\nEstablishing SAPI=3\n"); send_sabm(&bts_to_ms_channel, 3, NULL, 0); @@ -746,7 +742,7 @@ static void test_lapdm_desync() rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH"); CHECK_RC(rc); - OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cipher_compl_ack, ARRAY_SIZE(cipher_compl_ack)) == 0); + OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cp_data_1_ack, ARRAY_SIZE(cp_data_1_ack)) == 0); /* clean up */ lapdm_channel_exit(&bts_to_ms_channel); diff --git a/tests/lapd/lapd_test.ok b/tests/lapd/lapd_test.ok index a58a118c..e188e27e 100644 --- a/tests/lapd/lapd_test.ok +++ b/tests/lapd/lapd_test.ok @@ -68,27 +68,24 @@ Sending GPRS Suspend Request bts_to_ms_dummy_tx_cb: MS->BTS(us) message 22 Dumping queue: -00 00 17 [L2]> 03 20 0d [L3]> 06 35 01 -00 00 17 [L2]> 01 41 01 +00 00 17 [L2]> 03 40 0d [L3]> 06 35 01 Took message from DCCH queue: L2 header size 3, L3 size 20, SAP 0x1000000, 0/0, Link 0x00 -Message: [L2]> 03 20 0d [L3]> 06 35 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +Message: [L2]> 03 40 0d [L3]> 06 35 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b Sending Cipher Mode Complete bts_to_ms_dummy_tx_cb: MS->BTS(us) message 11 Dumping queue: -00 00 17 [L2]> 01 41 01 00 00 17 [L2]> 01 61 01 Took message from DCCH queue: L2 header size 23, L3 size 0, SAP 0x1000000, 0/0, Link 0x00 -Message: [L2]> 01 41 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +Message: [L2]> 01 61 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b Establishing SAPI=3 bts_to_ms_dummy_tx_cb: MS->BTS(us) message 6 Dumping queue: -00 00 17 [L2]> 01 61 01 Took message from DCCH queue: L2 header size 3, L3 size 20, SAP 0x1000000, 0/0, Link 0x03 Message: [L2]> 0d 73 01 [L3]> 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b @@ -96,8 +93,7 @@ Message: [L2]> 0d 73 01 [L3]> 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b Sending CP-DATA Dumping queue: -00 00 17 [L2]> 01 61 01 -Took message from DCCH queue: L2 header size 23, L3 size 0, SAP 0x1000000, 0/0, Link 0x00 -Message: [L2]> 01 61 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +Took message from DCCH queue: L2 header size 23, L3 size 0, SAP 0x1000000, 0/0, Link 0x03 +Message: [L2]> 0d 21 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b Success. -- cgit v1.2.3