[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)
This commit is contained in:
parent
4e03d6f822
commit
7b84cf805b
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue