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
} 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);
}
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) {
/* 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;
/* 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 */
/* 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
// 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;
/* 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) */
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
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);
struct gsm48_rrlayer *rr = &ms->rrlayer;
if (rr->modify_state) {
- struct msgb *nmsg;
uint16_t ma[64];
uint8_t ma_len;
/* 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 */