summaryrefslogtreecommitdiffstats
path: root/src/host
diff options
context:
space:
mode:
authorAndreas.Eversberg <jolly@eversberg.eu>2010-10-12 09:03:34 +0000
committerAndreas.Eversberg <jolly@eversberg.eu>2010-10-12 09:03:34 +0000
commit2a5e0f3cb7a4713e0aedb4c75878765978ebce02 (patch)
treee9bf3302a475dbb82e64ba933062f05b59b15f74 /src/host
parent16a5b93a19b656779712fdb1cf8af0a1cc0555f4 (diff)
[layer23] Fixed resume of datalink (after assignment or handover)
In order to resume correctly, the first message (ASSIGNMENT COMPLETE or HANDOVER COMPLETE) must be sent after the link is resumed. Therefore it must be given with the resume command. Unacknowledged messages are transmitted afterwards, if any.
Diffstat (limited to 'src/host')
-rw-r--r--src/host/layer23/src/common/lapdm.c16
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c61
2 files changed, 40 insertions, 37 deletions
diff --git a/src/host/layer23/src/common/lapdm.c b/src/host/layer23/src/common/lapdm.c
index ba191193..f06c738b 100644
--- a/src/host/layer23/src/common/lapdm.c
+++ b/src/host/layer23/src/common/lapdm.c
@@ -524,9 +524,8 @@ static void lapdm_t200_cb(void *data)
send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
/* send MDL ERROR INIDCATION to L3 */
rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
- /* flush buffers */
+ /* flush tx buffers */
lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
/* go back to idle state */
lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
/* NOTE: we must not change any other states or buffers
@@ -1871,9 +1870,8 @@ static int rslms_rx_rll_susp_req(struct msgb *msg, struct lapdm_datalink *dl)
} else
LOGP(DLAPDM, LOGL_INFO, "no frame in sendbuffer\n");
- /* Clear transmit and send buffer, if any */
+ /* Clear transmit buffer, but keep send buffer */
lapdm_dl_flush_tx(dl);
- lapdm_dl_flush_send(dl);
msgb_free(msg);
@@ -1906,13 +1904,19 @@ static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
}
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
- LOGP(DLAPDM, LOGL_INFO, "perform re-establishment (SABM)\n");
+ LOGP(DLAPDM, LOGL_INFO, "perform re-establishment (SABM) length=%d\n",
+ length);
/* Replace message in the send-buffer (reconnect) */
if (dl->send_buffer)
msgb_free(dl->send_buffer);
dl->send_out = 0;
- dl->send_buffer = msg;
+ if (length) {
+ /* Remove the RSL/RLL header */
+ msgb_pull_l2h(msg);
+ /* Write data into the send buffer, to be sent first */
+ dl->send_buffer = msg;
+ }
/* Discard partly received L3 message */
if (dl->rcv_buffer) {
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c
index 54df48e7..9e852691 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -3779,11 +3779,12 @@ static int gsm48_rr_tx_ass_cpl(struct osmocom_ms *ms, uint8_t cause)
/* RR_CAUSE */
ac->rr_cause = cause;
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg);
}
/* 9.1.4 sending ASSIGNMENT FAILURE */
-static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause)
+static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause,
+ uint8_t rsl_prim)
{
struct msgb *nmsg;
struct gsm48_hdr *gh;
@@ -3803,7 +3804,7 @@ static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause)
/* RR_CAUSE */
af->rr_cause = cause;
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, rsl_prim, nmsg);
}
/* 9.1.2 ASSIGNMENT COMMAND is received */
@@ -4073,15 +4074,15 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
/* check if channels are valid */
cause = gsm48_rr_check_mode(ms, cda->chan_nr, cda->mode);
if (cause)
- return gsm48_rr_tx_ass_fail(ms, cause);
+ return gsm48_rr_tx_ass_fail(ms, cause, RSL_MT_DATA_REQ);
if (before_time) {
cause = gsm48_rr_render_ma(ms, cdb, ma, &ma_len);
if (cause)
- return gsm48_rr_tx_ass_fail(ms, cause);
+ return gsm48_rr_tx_ass_fail(ms, cause, RSL_MT_DATA_REQ);
}
cause = gsm48_rr_render_ma(ms, cda, ma, &ma_len);
if (cause)
- return gsm48_rr_tx_ass_fail(ms, cause);
+ return gsm48_rr_tx_ass_fail(ms, cause, RSL_MT_DATA_REQ);
#if 0
@@ -4142,11 +4143,12 @@ static int gsm48_rr_tx_hando_cpl(struct osmocom_ms *ms, uint8_t cause)
// FIXME: mobile observed time
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg);
}
/* 9.1.4 sending HANDOVER FAILURE */
-static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause)
+static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause,
+ uint8_t rsl_prim)
{
struct msgb *nmsg;
struct gsm48_hdr *gh;
@@ -4166,7 +4168,7 @@ static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause)
/* RR_CAUSE */
hf->rr_cause = cause;
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ return gsm48_send_rsl(ms, rsl_prim, nmsg);
}
/* receiving HANDOVER COMMAND message (9.1.15) */
@@ -4455,11 +4457,11 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
if (before_time) {
cause = gsm48_rr_render_ma(ms, cdb, ma, &ma_len);
if (cause)
- return gsm48_rr_tx_hando_fail(ms, cause);
+ return gsm48_rr_tx_hando_fail(ms, cause, RSL_MT_DATA_REQ);
}
cause = gsm48_rr_render_ma(ms, cda, ma, &ma_len);
if (cause)
- return gsm48_rr_tx_hando_fail(ms, cause);
+ return gsm48_rr_tx_hando_fail(ms, cause, RSL_MT_DATA_REQ);
#if 0
@@ -4518,21 +4520,6 @@ static int gsm48_rr_estab_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "data link is resumed\n");
- switch (rr->modify_state) {
- case GSM48_RR_MOD_ASSIGN:
- gsm48_rr_tx_ass_cpl(ms, GSM48_RR_CAUSE_NORMAL);
- break;
- case GSM48_RR_MOD_HANDO:
- gsm48_rr_tx_hando_cpl(ms, GSM48_RR_CAUSE_NORMAL);
- break;
- case GSM48_RR_MOD_ASSIGN_RESUME:
- gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
- break;
- case GSM48_RR_MOD_HANDO_RESUME:
- gsm48_rr_tx_hando_fail(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
- break;
- }
-
/* transmit queued frames during ho / ass transition */
gsm48_rr_dequeue_down(ms);
@@ -4547,7 +4534,6 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_rrlayer *rr = &ms->rrlayer;
if (rr->modify_state) {
- struct msgb *nmsg;
uint16_t ma[64];
uint8_t ma_len;
@@ -4589,10 +4575,23 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
/* send DL-RESUME REQUEST */
LOGP(DRR, LOGL_INFO, "request resume of data link\n");
- nmsg = gsm48_l3_msgb_alloc();
- if (!nmsg)
- return -ENOMEM;
- gsm48_send_rsl(ms, RSL_MT_RES_REQ, nmsg);
+ switch (rr->modify_state) {
+ case GSM48_RR_MOD_ASSIGN:
+ gsm48_rr_tx_ass_cpl(ms, GSM48_RR_CAUSE_NORMAL);
+ break;
+ case GSM48_RR_MOD_HANDO:
+ gsm48_rr_tx_hando_cpl(ms, GSM48_RR_CAUSE_NORMAL);
+ break;
+ case GSM48_RR_MOD_ASSIGN_RESUME:
+ gsm48_rr_tx_ass_fail(ms, GSM48_RR_CAUSE_PROT_ERROR_UNSPC,
+ RSL_MT_RECON_REQ);
+ break;
+ case GSM48_RR_MOD_HANDO_RESUME:
+ gsm48_rr_tx_hando_fail(ms,
+ GSM48_RR_CAUSE_PROT_ERROR_UNSPC,
+ RSL_MT_RECON_REQ);
+ break;
+ }
#ifdef TODO
/* trigger RACH */