From 7b84cf805b83fee946f1319225c8dff1c25c0f73 Mon Sep 17 00:00:00 2001 From: "Andreas.Eversberg" Date: Sat, 26 Jun 2010 11:12:25 +0000 Subject: [PATCH] [lapdm] Added flow control between L1 and L2, so DM mode does not crash. In dedicated mode a frame is sent to layer 1. Subsequent frames are queued inside lapdm.c until a confirm from layer 1 is received. Since not all pending frames are sent rapidly at once, the layer 1 does not crash anymore. Also included in this commit: handling of reset confirm (maybe required in the future after dedicated mode) --- src/host/layer23/include/osmocom/l1ctl.h | 3 ++ src/host/layer23/include/osmocom/lapdm.h | 1 + src/host/layer23/src/app_mobile.c | 5 +-- src/host/layer23/src/gsm322.c | 4 ++ src/host/layer23/src/gsm48_rr.c | 3 +- src/host/layer23/src/l1ctl.c | 50 +++++++++++++++++++----- src/host/layer23/src/lapdm.c | 34 ++++++++++++---- 7 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/host/layer23/include/osmocom/l1ctl.h b/src/host/layer23/include/osmocom/l1ctl.h index ad59b2d43..cac37cf72 100644 --- a/src/host/layer23/include/osmocom/l1ctl.h +++ b/src/host/layer23/include/osmocom/l1ctl.h @@ -32,6 +32,9 @@ int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode); int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len); +/* Transmit L1CTL_RESET_REQ */ +int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type); + /* Transmit L1CTL_PM_REQ */ int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from, uint16_t arfcm_to); diff --git a/src/host/layer23/include/osmocom/lapdm.h b/src/host/layer23/include/osmocom/lapdm.h index f1f4ed5cc..06ac5f89e 100644 --- a/src/host/layer23/include/osmocom/lapdm.h +++ b/src/host/layer23/include/osmocom/lapdm.h @@ -78,6 +78,7 @@ void lapdm_exit(struct lapdm_entity *le); /* input into layer2 (from layer 1) */ int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i); +int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le); /* input into layer2 (from layer 3) */ int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms); diff --git a/src/host/layer23/src/app_mobile.c b/src/host/layer23/src/app_mobile.c index 9e8938cb9..a7a1215da 100644 --- a/src/host/layer23/src/app_mobile.c +++ b/src/host/layer23/src/app_mobile.c @@ -80,11 +80,8 @@ static int signal_cb(unsigned int subsys, unsigned int signal, switch (signal) { case S_L1CTL_RESET: - if (started) { - printf("L1_RESET, TODO: resend last radio request " - "(CCCH / dedicated / power scan)\n"); + if (started) break; - } started = 1; ms = signal_data; /* insert test card, if enabled */ diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c index 8c51d0136..672f77ed1 100644 --- a/src/host/layer23/src/gsm322.c +++ b/src/host/layer23/src/gsm322.c @@ -221,6 +221,7 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg) static int gsm322_sync_to_cell(struct osmocom_ms *ms, struct gsm322_cellsel *cs) { +// l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL); return l1ctl_tx_fbsb_req(ms, cs->arfcn, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_COMBINED); @@ -2404,6 +2405,9 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal, ms = rc->ms; gsm48_rr_rach_conf(ms, rc->fn); break; + case S_L1CTL_RESET: + LOGP(DCS, LOGL_INFO, "Reset\n"); + break; } return 0; diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c index 415adc425..20580b2b9 100644 --- a/src/host/layer23/src/gsm48_rr.c +++ b/src/host/layer23/src/gsm48_rr.c @@ -215,7 +215,8 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state) struct msgb *msg, *nmsg; /* release dedicated mode, if any */ - tx_ph_dm_rel_req(rr->ms); +// tx_ph_dm_rel_req(rr->ms); + l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_FULL); /* free establish message, if any */ rr->rr_est_req = 0; if (rr->rr_est_msg) { diff --git a/src/host/layer23/src/l1ctl.c b/src/host/layer23/src/l1ctl.c index 6e5920440..38d4f5d22 100644 --- a/src/host/layer23/src/l1ctl.c +++ b/src/host/layer23/src/l1ctl.c @@ -208,6 +208,26 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg) return 0; } +/* Receive L1CTL_DATA_CONF (Data Confirm from L1) */ +static int rx_ph_data_conf(struct osmocom_ms *ms, struct msgb *msg) +{ + struct l1ctl_info_dl *dl; + struct lapdm_entity *le; + + dl = (struct l1ctl_info_dl *) msg->l1h; + + /* determine LAPDm entity based on SACCH or not */ + if (dl->link_id & 0x40) + le = &ms->l2_entity.lapdm_acch; + else + le = &ms->l2_entity.lapdm_dcch; + + /* send it up into LAPDm */ + l2_ph_data_conf(msg, le); + + return 0; +} + /* Transmit L1CTL_DATA_REQ */ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg, uint8_t chan_nr, uint8_t link_id) @@ -397,6 +417,23 @@ int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from, return osmo_send_l1(ms, msg); } +/* Transmit L1CTL_RESET_REQ */ +int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type) +{ + struct msgb *msg; + struct l1ctl_reset *res; + + msg = osmo_l1_alloc(L1CTL_RESET_REQ); + if (!msg) + return -1; + + printf("Tx Reset Req (%u)\n", type); + res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res)); + res->type = type; + + return osmo_send_l1(ms, msg); +} + /* Receive L1CTL_RESET_IND */ static int rx_l1_reset(struct osmocom_ms *ms) { @@ -452,7 +489,11 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg) case L1CTL_DATA_IND: rc = rx_ph_data_ind(ms, msg); break; + case L1CTL_DATA_CONF: + rc = rx_ph_data_conf(ms, msg); + break; case L1CTL_RESET_IND: + case L1CTL_RESET_CONF: rc = rx_l1_reset(ms); msgb_free(msg); break; @@ -462,19 +503,10 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg) if (l1h->flags & L1CTL_F_DONE) dispatch_signal(SS_L1CTL, S_L1CTL_PM_DONE, ms); break; - case L1CTL_RESET_CONF: - LOGP(DL1C, LOGL_NOTICE, "L1CTL_RESET_CONF\n"); - msgb_free(msg); - break; case L1CTL_RACH_CONF: - LOGP(DL1C, LOGL_NOTICE, "L1CTL_RACH_CONF\n"); rc = rx_l1_rach_conf(ms, msg); msgb_free(msg); break; - case L1CTL_DATA_CONF: - LOGP(DL1C, LOGL_NOTICE, "L1CTL_DATA_CONF\n"); - msgb_free(msg); - break; default: fprintf(stderr, "Unknown MSG: %u\n", l1h->msg_type); msgb_free(msg); diff --git a/src/host/layer23/src/lapdm.c b/src/host/layer23/src/lapdm.c index c3a86b187..fea63c1b5 100644 --- a/src/host/layer23/src/lapdm.c +++ b/src/host/layer23/src/lapdm.c @@ -297,14 +297,13 @@ static int tx_ph_data_enqueue(struct lapdm_datalink *dl, struct msgb *msg, /* send the frame now */ le->tx_pending = 1; -#warning HACK: no confirm yet! (queue is always empty now) -le->tx_pending = 0; +#if 0 printf("-> tx chan_nr 0x%x link_id 0x%x len %d data", chan_nr, link_id, msgb_l2len(msg)); int i; for (i = 0; i < msgb_l2len(msg); i++) printf(" %02x", msg->l2h[i]); printf("\n"); -//usleep(100000); +#endif lapdm_pad_msgb(msg, n201); return tx_ph_data_req(ms, msg, chan_nr, link_id); } @@ -312,15 +311,23 @@ printf("\n"); /* get next frame from the tx queue. because the ms has multiple datalinks, * each datalink's queue is read round-robin. */ -static int tx_ph_data_dequeue(struct lapdm_entity *le) +int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le) { struct osmocom_ms *ms = le->ms; struct lapdm_datalink *dl; int last = le->last_tx_dequeue; int i = last, n = ARRAY_SIZE(le->datalink); - struct msgb *msg; uint8_t chan_nr, link_id, n201; + /* we may send again */ + le->tx_pending = 0; + +#if 0 +printf("-> tx confirm\n"); +#endif + /* free confirm message */ + msgb_free(msg); + /* round-robin dequeue */ do { /* next */ @@ -331,7 +338,7 @@ static int tx_ph_data_dequeue(struct lapdm_entity *le) } while (i != last); /* no message in all queues */ - if (msg) + if (!msg) return 0; /* Pull chan_nr and link_id */ @@ -347,6 +354,12 @@ static int tx_ph_data_dequeue(struct lapdm_entity *le) /* Pad the frame, we can transmit now */ le->tx_pending = 1; +#if 0 +printf("-> more tx chan_nr 0x%x link_id 0x%x len %d data", chan_nr, link_id, msgb_l2len(msg)); +for (i = 0; i < msgb_l2len(msg); i++) + printf(" %02x", msg->l2h[i]); +printf("\n"); +#endif lapdm_pad_msgb(msg, n201); return tx_ph_data_req(ms, msg, chan_nr, link_id); } @@ -1419,6 +1432,13 @@ static int lapdm_ph_data_ind(struct msgb *msg, struct lapdm_msg_ctx *mctx) { int rc; +#if 0 +printf("-> rx chan_nr 0x%x link_id 0x%x len %d data", mctx->chan_nr, mctx->link_id, msgb_l2len(msg)); +int i; +for (i = 0; i < msgb_l2len(msg); i++) + printf(" %02x", msg->l2h[i]); +printf("\n"); +#endif /* G.2.3 EA bit set to "0" is not allowed in GSM */ if (!LAPDm_ADDR_EA(mctx->addr)) { LOGP(DLAPDM, LOGL_NOTICE, "EA bit 0 is not allowed in GSM\n"); @@ -1959,7 +1979,7 @@ const char *lapdm_state_names[] = { "LAPDm_STATE_SABM_SENT", "LAPDm_STATE_MF_EST", "LAPDm_STATE_TIMER_RECOV", - "LAPDm_STATE_OWN_RCVR_BUSY" + "LAPDm_STATE_DISC_SENT", }; /* statefull handling for RSLms RLL messages from L3 */