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.
send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
/* send MDL ERROR INIDCATION to L3 */
rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
send_rll_simple(RSL_MT_REL_IND, &dl->mctx);
/* send MDL ERROR INIDCATION to L3 */
rsl_rll_error(RLL_CAUSE_T200_EXPIRED, &dl->mctx);
- 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
/* go back to idle state */
lapdm_dl_newstate(dl, LAPDm_STATE_IDLE);
/* NOTE: we must not change any other states or buffers
} else
LOGP(DLAPDM, LOGL_INFO, "no frame in sendbuffer\n");
} 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_send(dl);
}
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
}
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;
/* Replace message in the send-buffer (reconnect) */
if (dl->send_buffer)
msgb_free(dl->send_buffer);
dl->send_out = 0;
+ 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) {
/* Discard partly received L3 message */
if (dl->rcv_buffer) {
/* RR_CAUSE */
ac->rr_cause = 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 */
}
/* 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;
{
struct msgb *nmsg;
struct gsm48_hdr *gh;
/* RR_CAUSE */
af->rr_cause = 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 */
}
/* 9.1.2 ASSIGNMENT COMMAND is received */
/* check if channels are valid */
cause = gsm48_rr_check_mode(ms, cda->chan_nr, cda->mode);
if (cause)
/* 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)
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)
}
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);
// FIXME: mobile observed time
// 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 */
}
/* 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;
{
struct msgb *nmsg;
struct gsm48_hdr *gh;
/* RR_CAUSE */
hf->rr_cause = 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) */
}
/* receiving HANDOVER COMMAND message (9.1.15) */
if (before_time) {
cause = gsm48_rr_render_ma(ms, cdb, ma, &ma_len);
if (cause)
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)
}
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);
LOGP(DRR, LOGL_INFO, "data link is resumed\n");
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);
/* transmit queued frames during ho / ass transition */
gsm48_rr_dequeue_down(ms);
struct gsm48_rrlayer *rr = &ms->rrlayer;
if (rr->modify_state) {
struct gsm48_rrlayer *rr = &ms->rrlayer;
if (rr->modify_state) {
uint16_t ma[64];
uint8_t ma_len;
uint16_t ma[64];
uint8_t ma_len;
/* send DL-RESUME REQUEST */
LOGP(DRR, LOGL_INFO, "request resume of data link\n");
/* 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 */
#ifdef TODO
/* trigger RACH */