fixeria submitted this change.

View Change


Approvals: osmith: Looks good to me, but someone else must approve fixeria: Looks good to me, approved Jenkins Builder: Verified pespin: Looks good to me, but someone else must approve
modem: grr: implement RACH.req retransmission

Sometimes sending one Access Burst is not enough, so we need to repeat
sending it a few more more times changing the 3 LSBs randomly. This
is what we already do in the mobile app, but not in the modem app.

* Rename GRR_EV_RACH_{REQ,CNF} to GRR_EV_CHAN_ACCESS_{REQ,CNF}.
* Rename VTY command 'grr tx-chan-req' to 'grr start-chan-access'.
* Add an intermediate state GRR_ST_PACKET_ACCESS.
** The GRR_EV_CHAN_ACCESS_REQ transitions to this state.
** One RACH.req gets transmitted when entering this state.
** The GRR_EV_CHAN_ACCESS_CNF confirms transmission of a RACH.req.
** Upon the timeout (300 ms) expiry, a loop state transition happens.
** After 3 loop-transitions, transition to GRR_ST_PACKET_NOT_READY.

Change-Id: Iab6d9147f6e0aeb99239affacf318a3897fd6ffe
Related: libosmo-gprs.git If0de3ed86b1e2897d70183f3b0f4fbfd7d2bda80
Related: OS#5500, OS#6131
---
M src/host/layer23/include/osmocom/bb/modem/grr.h
M src/host/layer23/src/modem/grr.c
M src/host/layer23/src/modem/rlcmac.c
M src/host/layer23/src/modem/vty.c
4 files changed, 189 insertions(+), 78 deletions(-)

diff --git a/src/host/layer23/include/osmocom/bb/modem/grr.h b/src/host/layer23/include/osmocom/bb/modem/grr.h
index 8235d59..99800ad 100644
--- a/src/host/layer23/include/osmocom/bb/modem/grr.h
+++ b/src/host/layer23/include/osmocom/bb/modem/grr.h
@@ -11,14 +11,15 @@
enum grr_fsm_state {
GRR_ST_PACKET_NOT_READY,
GRR_ST_PACKET_IDLE,
+ GRR_ST_PACKET_ACCESS,
GRR_ST_PACKET_TRANSFER,
};

enum grr_fsm_event {
GRR_EV_BCCH_BLOCK_IND,
GRR_EV_PCH_AGCH_BLOCK_IND,
- GRR_EV_RACH_REQ,
- GRR_EV_RACH_CNF,
+ GRR_EV_CHAN_ACCESS_REQ,
+ GRR_EV_CHAN_ACCESS_CNF,
GRR_EV_PDCH_ESTABLISH_REQ,
GRR_EV_PDCH_RELEASE_REQ,
GRR_EV_PDCH_UL_TBF_CFG_REQ,
@@ -31,4 +32,3 @@
extern struct osmo_fsm grr_fsm_def;

int modem_grr_rslms_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
-uint8_t modem_grr_gen_chan_req(bool single_block);
diff --git a/src/host/layer23/src/modem/grr.c b/src/host/layer23/src/modem/grr.c
index af773a3..a029dd8 100644
--- a/src/host/layer23/src/modem/grr.c
+++ b/src/host/layer23/src/modem/grr.c
@@ -63,7 +63,7 @@
}

/* Generate an 8-bit CHANNEL REQUEST message as per 3GPP TS 44.018, 9.1.8 */
-uint8_t modem_grr_gen_chan_req(bool single_block)
+static uint8_t grr_gen_chan_req(bool single_block)
{
uint8_t rnd = (uint8_t)rand();

@@ -408,7 +408,7 @@

switch (ch->c.msg_type) {
case RSL_MT_CHAN_CONF: /* RACH.conf */
- return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_RACH_CNF,
+ return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_CHAN_ACCESS_CNF,
(void *)&ch->data[1]);
default:
LOGP(DRSL, LOGL_NOTICE, "Unhandled RSLms CCHAN message "
@@ -449,6 +449,78 @@

#include <osmocom/gsm/gsm0502.h> // XXX

+/* RACH re-transmission delay value (in ms) */
+#define GRR_PACKET_ACCESS_DELAY_MS 300
+/* RACH max number of transmissions */
+#define GRR_PACKET_ACCESS_MAX_CHAN_REQ 3
+
+static void handle_chan_access_req(struct osmo_fsm_inst *fi,
+ const struct osmo_gprs_rlcmac_l1ctl_prim *lp)
+{
+ struct osmocom_ms *ms = fi->priv;
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+
+ if (lp->rach_req.is_11bit) { /* TODO: implement 11-bit RACH */
+ LOGPFSML(fi, LOGL_ERROR, "11-bit RACH is not supported\n");
+ return;
+ }
+
+ memset(&rr->cr_hist[0], 0x00, sizeof(rr->cr_hist));
+ rr->chan_req_val = lp->rach_req.ra & ~0x07;
+ rr->n_chan_req = GRR_PACKET_ACCESS_MAX_CHAN_REQ;
+ rr->state = GSM48_RR_ST_CONN_PEND;
+
+ osmo_fsm_inst_state_chg_ms(fi, GRR_ST_PACKET_ACCESS,
+ GRR_PACKET_ACCESS_DELAY_MS, 0);
+}
+
+static void handle_pdch_establish_req(struct osmo_fsm_inst *fi,
+ const struct osmo_gprs_rlcmac_l1ctl_prim *lp)
+{
+ struct osmocom_ms *ms = fi->priv;
+
+ if (!lp->pdch_est_req.fh) {
+ LOGPFSML(fi, LOGL_INFO,
+ "PDCH Establish.Req: TSC=%u, H0, ARFCN=%u\n",
+ lp->pdch_est_req.tsc, lp->pdch_est_req.arfcn);
+ l1ctl_tx_dm_est_req_h0(ms, lp->pdch_est_req.arfcn,
+ RSL_CHAN_OSMO_PDCH | lp->pdch_est_req.ts_nr,
+ lp->pdch_est_req.tsc, GSM48_CMODE_SIGN, 0);
+ } else {
+ /* Hopping */
+ uint8_t ma_len = 0;
+ uint16_t ma[64];
+
+ LOGPFSML(fi, LOGL_INFO,
+ "PDCH Establish.Req: TSC=%u, H1, HSN=%u, MAIO=%u\n",
+ lp->pdch_est_req.tsc,
+ lp->pdch_est_req.fhp.hsn,
+ lp->pdch_est_req.fhp.maio);
+
+ for (unsigned int i = 1, j = 0; i <= 1024; i++) {
+ unsigned int arfcn = i & 1023;
+ unsigned int k;
+
+ if (~ms->cellsel.sel_si.freq[arfcn].mask & 0x01)
+ continue;
+
+ k = lp->pdch_est_req.fhp.ma_len - (j >> 3) - 1;
+ if (lp->pdch_est_req.fhp.ma[k] & (1 << (j & 7)))
+ ma[ma_len++] = arfcn;
+ j++;
+ }
+
+ l1ctl_tx_dm_est_req_h1(ms,
+ lp->pdch_est_req.fhp.maio,
+ lp->pdch_est_req.fhp.hsn,
+ &ma[0], ma_len,
+ RSL_CHAN_OSMO_PDCH | lp->pdch_est_req.ts_nr,
+ lp->pdch_est_req.tsc, GSM48_CMODE_SIGN, 0);
+ }
+
+ osmo_fsm_inst_state_chg(fi, GRR_ST_PACKET_TRANSFER, 0, 0);
+}
+
static void handle_pdch_block_ind(struct osmocom_ms *ms, struct msgb *msg)
{
const struct l1ctl_gprs_dl_block_ind *ind = (void *)msg->l1h;
@@ -547,27 +619,60 @@
case GRR_EV_PCH_AGCH_BLOCK_IND:
grr_rx_ccch(ms, (struct msgb *)data);
break;
- case GRR_EV_RACH_REQ:
- {
- const struct osmo_gprs_rlcmac_l1ctl_prim *lp = data;
- struct gsm48_rrlayer *rr = &ms->rrlayer;
-
- if (lp->rach_req.is_11bit) { /* TODO: implement 11-bit RACH */
- LOGPFSML(fi, LOGL_ERROR, "11-bit RACH is not supported\n");
- return;
- }
-
- rr->cr_ra = lp->rach_req.ra;
- memset(&rr->cr_hist[0], 0x00, sizeof(rr->cr_hist));
-
- LOGPFSML(fi, LOGL_INFO, "Sending CHANNEL REQUEST (0x%02x)\n", rr->cr_ra);
- l1ctl_tx_rach_req(ms, RSL_CHAN_RACH, 0x00, rr->cr_ra, 0,
- ms->cellsel.ccch_mode == CCCH_MODE_COMBINED);
-
- rr->state = GSM48_RR_ST_CONN_PEND;
+ case GRR_EV_CHAN_ACCESS_REQ:
+ handle_chan_access_req(fi, data);
break;
+ case GRR_EV_PDCH_ESTABLISH_REQ:
+ handle_pdch_establish_req(fi, data);
+ break;
+ default:
+ OSMO_ASSERT(0);
}
- case GRR_EV_RACH_CNF:
+}
+
+static void grr_st_packet_access_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct osmocom_ms *ms = fi->priv;
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+
+ if (rr->n_chan_req == 0) {
+ LOGPFSML(fi, LOGL_ERROR, "Packet access failed (no more attempts left)\n");
+ osmo_fsm_inst_state_chg(fi, GRR_ST_PACKET_NOT_READY, 0, 0);
+ return;
+ }
+
+ /* (re-)generate the RA value */
+ if ((rr->chan_req_val >> 3) == 0x0e) /* 01110xxx */
+ rr->cr_ra = grr_gen_chan_req(true);
+ else /* 011110xx or 01111x0x or 01111xx0 */
+ rr->cr_ra = grr_gen_chan_req(false);
+ rr->n_chan_req--;
+
+ LOGPFSML(fi, LOGL_INFO,
+ "Sending CHANNEL REQUEST (ra=0x%02x, num_attempts=%u)\n",
+ rr->cr_ra, rr->n_chan_req);
+
+ l1ctl_tx_rach_req(ms, RSL_CHAN_RACH, 0x00, rr->cr_ra, 0,
+ ms->cellsel.ccch_mode == CCCH_MODE_COMBINED);
+}
+
+static void grr_st_packet_access_action(struct osmo_fsm_inst *fi,
+ uint32_t event, void *data)
+{
+ struct osmocom_ms *ms = fi->priv;
+
+ switch (event) {
+ case GRR_EV_BCCH_BLOCK_IND:
+ grr_rx_bcch(ms, (struct msgb *)data);
+ if (!grr_cell_is_usable(ms)) {
+ LOGPFSML(fi, LOGL_NOTICE, "Cell is not usable, GRR becomes not ready\n");
+ osmo_fsm_inst_state_chg(fi, GRR_ST_PACKET_NOT_READY, 0, 0);
+ }
+ break;
+ case GRR_EV_PCH_AGCH_BLOCK_IND:
+ grr_rx_ccch(ms, (struct msgb *)data);
+ break;
+ case GRR_EV_CHAN_ACCESS_CNF:
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
const struct gsm48_req_ref *ref = data;
@@ -591,50 +696,8 @@
break;
}
case GRR_EV_PDCH_ESTABLISH_REQ:
- {
- const struct osmo_gprs_rlcmac_l1ctl_prim *lp = data;
-
- if (!lp->pdch_est_req.fh) {
- LOGPFSML(fi, LOGL_INFO,
- "PDCH Establish.Req: TSC=%u, H0, ARFCN=%u\n",
- lp->pdch_est_req.tsc, lp->pdch_est_req.arfcn);
- l1ctl_tx_dm_est_req_h0(ms, lp->pdch_est_req.arfcn,
- RSL_CHAN_OSMO_PDCH | lp->pdch_est_req.ts_nr,
- lp->pdch_est_req.tsc, GSM48_CMODE_SIGN, 0);
- } else {
- /* Hopping */
- uint8_t ma_len = 0;
- uint16_t ma[64];
-
- LOGPFSML(fi, LOGL_INFO,
- "PDCH Establish.Req: TSC=%u, H1, HSN=%u, MAIO=%u\n",
- lp->pdch_est_req.tsc,
- lp->pdch_est_req.fhp.hsn,
- lp->pdch_est_req.fhp.maio);
-
- for (unsigned int i = 1, j = 0; i <= 1024; i++) {
- unsigned int arfcn = i & 1023;
- unsigned int k;
-
- if (~ms->cellsel.sel_si.freq[arfcn].mask & 0x01)
- continue;
-
- k = lp->pdch_est_req.fhp.ma_len - (j >> 3) - 1;
- if (lp->pdch_est_req.fhp.ma[k] & (1 << (j & 7)))
- ma[ma_len++] = arfcn;
- j++;
- }
-
- l1ctl_tx_dm_est_req_h1(ms,
- lp->pdch_est_req.fhp.maio,
- lp->pdch_est_req.fhp.hsn,
- &ma[0], ma_len,
- RSL_CHAN_OSMO_PDCH | lp->pdch_est_req.ts_nr,
- lp->pdch_est_req.tsc, GSM48_CMODE_SIGN, 0);
- }
- osmo_fsm_inst_state_chg(fi, GRR_ST_PACKET_TRANSFER, 0, 0);
+ handle_pdch_establish_req(fi, data);
break;
- }
default:
OSMO_ASSERT(0);
}
@@ -704,6 +767,19 @@
}
}

+static int grr_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ switch (fi->state) {
+ case GRR_ST_PACKET_ACCESS:
+ /* perform a loop transaction, restarting the timer */
+ osmo_fsm_inst_state_chg_ms(fi, GRR_ST_PACKET_ACCESS,
+ GRR_PACKET_ACCESS_DELAY_MS, 0);
+ return 0;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
static const struct osmo_fsm_state grr_fsm_states[] = {
[GRR_ST_PACKET_NOT_READY] = {
.name = "PACKET_NOT_READY",
@@ -715,15 +791,26 @@
[GRR_ST_PACKET_IDLE] = {
.name = "PACKET_IDLE",
.out_state_mask = S(GRR_ST_PACKET_NOT_READY)
+ | S(GRR_ST_PACKET_ACCESS)
| S(GRR_ST_PACKET_TRANSFER),
.in_event_mask = S(GRR_EV_BCCH_BLOCK_IND)
| S(GRR_EV_PCH_AGCH_BLOCK_IND)
- | S(GRR_EV_RACH_REQ)
- | S(GRR_EV_RACH_CNF)
- | S(GRR_EV_PDCH_ESTABLISH_REQ),
+ | S(GRR_EV_CHAN_ACCESS_REQ)
+ | S(GRR_EV_PDCH_ESTABLISH_REQ), /* DL TBF ASS */
.action = &grr_st_packet_idle_action,
.onenter = &grr_st_packet_idle_onenter,
},
+ [GRR_ST_PACKET_ACCESS] = {
+ .name = "PACKET_ACCESS",
+ .out_state_mask = S(GRR_ST_PACKET_NOT_READY)
+ | S(GRR_ST_PACKET_TRANSFER),
+ .in_event_mask = S(GRR_EV_BCCH_BLOCK_IND)
+ | S(GRR_EV_PCH_AGCH_BLOCK_IND)
+ | S(GRR_EV_CHAN_ACCESS_CNF)
+ | S(GRR_EV_PDCH_ESTABLISH_REQ), /* UL TBF ASS */
+ .onenter = &grr_st_packet_access_onenter,
+ .action = &grr_st_packet_access_action,
+ },
[GRR_ST_PACKET_TRANSFER] = {
.name = "PACKET_TRANSFER",
.out_state_mask = S(GRR_ST_PACKET_NOT_READY),
@@ -742,8 +829,8 @@
static const struct value_string grr_fsm_event_names[] = {
OSMO_VALUE_STRING(GRR_EV_BCCH_BLOCK_IND),
OSMO_VALUE_STRING(GRR_EV_PCH_AGCH_BLOCK_IND),
- OSMO_VALUE_STRING(GRR_EV_RACH_REQ),
- OSMO_VALUE_STRING(GRR_EV_RACH_CNF),
+ OSMO_VALUE_STRING(GRR_EV_CHAN_ACCESS_REQ),
+ OSMO_VALUE_STRING(GRR_EV_CHAN_ACCESS_CNF),
OSMO_VALUE_STRING(GRR_EV_PDCH_ESTABLISH_REQ),
OSMO_VALUE_STRING(GRR_EV_PDCH_RELEASE_REQ),
OSMO_VALUE_STRING(GRR_EV_PDCH_UL_TBF_CFG_REQ),
@@ -760,6 +847,7 @@
.states = grr_fsm_states,
.num_states = ARRAY_SIZE(grr_fsm_states),
.event_names = grr_fsm_event_names,
+ .timer_cb = &grr_fsm_timer_cb,
};

static __attribute__((constructor)) void on_dso_load(void)
diff --git a/src/host/layer23/src/modem/rlcmac.c b/src/host/layer23/src/modem/rlcmac.c
index 5037d99..a9588f7 100644
--- a/src/host/layer23/src/modem/rlcmac.c
+++ b/src/host/layer23/src/modem/rlcmac.c
@@ -145,7 +145,7 @@

switch (OSMO_PRIM_HDR(&prim->oph)) {
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_RACH, PRIM_OP_REQUEST):
- return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_RACH_REQ, lp);
+ return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_CHAN_ACCESS_REQ, lp);
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_REQUEST):
return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_PDCH_BLOCK_REQ, lp);
case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, PRIM_OP_REQUEST):
diff --git a/src/host/layer23/src/modem/vty.c b/src/host/layer23/src/modem/vty.c
index da29165..f42aa66 100644
--- a/src/host/layer23/src/modem/vty.c
+++ b/src/host/layer23/src/modem/vty.c
@@ -73,27 +73,26 @@
/* testing commands */
DEFUN_HIDDEN(test_grr_tx_chan_req,
test_grr_tx_chan_req_cmd,
- "test MS_NAME grr tx-chan-req (1phase|2phase)",
+ "test MS_NAME grr start-chan-access (1phase|2phase)",
TEST_CMD_DESC MS_NAME_DESC GRR_CMDG_DESC
"Send a CHANNEL REQUEST (RACH) to the network\n"
"One-phase packet access (011110xx or 01111x0x or 01111xx0)\n"
"Two-phase (single block) packet access (01110xxx)\n")
{
struct osmocom_ms *ms;
- uint8_t chan_req;

if ((ms = l23_vty_get_ms(argv[0], vty)) == NULL)
return CMD_WARNING;

- chan_req = modem_grr_gen_chan_req(argv[1][0] == '2');
const struct osmo_gprs_rlcmac_l1ctl_prim lp = {
.rach_req = {
.is_11bit = false,
- .ra = chan_req,
+ /* the 3 LSBs are randomized during (re)transmission */
+ .ra = argv[1][0] == '1' ? 0x78 : 0x70,
}
};

- if (osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_RACH_REQ, (void *)&lp)) {
+ if (osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_CHAN_ACCESS_REQ, (void *)&lp)) {
vty_out(vty, "Failed to send a CHANNEL REQUEST%s", VTY_NEWLINE);
return CMD_WARNING;
}

To view, visit change 34514. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: Iab6d9147f6e0aeb99239affacf318a3897fd6ffe
Gerrit-Change-Number: 34514
Gerrit-PatchSet: 2
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: osmith <osmith@sysmocom.de>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-MessageType: merged