diff --git a/src/host/layer23/include/osmocom/bb/common/ms.h b/src/host/layer23/include/osmocom/bb/common/ms.h index 0b3e13cce..36d3e3bae 100644 --- a/src/host/layer23/include/osmocom/bb/common/ms.h +++ b/src/host/layer23/include/osmocom/bb/common/ms.h @@ -42,6 +42,7 @@ struct osmosap_entity { struct osmol1_entity { int (*l1_traffic_ind)(struct osmocom_ms *ms, struct msgb *msg); + int (*l1_gprs_ul_block_cnf)(struct osmocom_ms *ms, struct msgb *msg); int (*l1_gprs_dl_block_ind)(struct osmocom_ms *ms, struct msgb *msg); int (*l1_gprs_rts_ind)(struct osmocom_ms *ms, struct msgb *msg); }; diff --git a/src/host/layer23/include/osmocom/bb/modem/grr.h b/src/host/layer23/include/osmocom/bb/modem/grr.h index 99800ad3e..a86a089b9 100644 --- a/src/host/layer23/include/osmocom/bb/modem/grr.h +++ b/src/host/layer23/include/osmocom/bb/modem/grr.h @@ -25,6 +25,7 @@ enum grr_fsm_event { GRR_EV_PDCH_UL_TBF_CFG_REQ, GRR_EV_PDCH_DL_TBF_CFG_REQ, GRR_EV_PDCH_BLOCK_REQ, + GRR_EV_PDCH_BLOCK_CNF, GRR_EV_PDCH_BLOCK_IND, GRR_EV_PDCH_RTS_IND, }; diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c index a0f25b8d0..949791030 100644 --- a/src/host/layer23/src/common/l1ctl.c +++ b/src/host/layer23/src/common/l1ctl.c @@ -949,6 +949,36 @@ static int rx_l1_neigh_pm_ind(struct osmocom_ms *ms, struct msgb *msg) return 0; } +/* Receive L1CTL_GPRS_UL_BLOCK_CNF */ +static int rx_l1_gprs_ul_block_cnf(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct l1ctl_gprs_ul_block_cnf *cnf = (void *)msg->l1h; + + if (msgb_l1len(msg) < sizeof(*cnf)) { + LOGP(DL1C, LOGL_ERROR, + "Rx malformed GPRS UL BLOCK.cnf (len=%u < %zu)\n", + msgb_l1len(msg), sizeof(*cnf)); + return -EINVAL; + } + if (OSMO_UNLIKELY(cnf->tn >= 8)) { + LOGP(DL1C, LOGL_ERROR, + "Rx malformed GPRS UL BLOCK.cnf (tn=%u)\n", cnf->tn); + return -EINVAL; + } + + msg->l2h = (void *)&cnf->data[0]; + + DEBUGP(DL1C, "Rx GPRS UL BLOCK.cnf (fn=%u, tn=%u, len=%u): %s\n", + ntohl(cnf->fn), cnf->tn, msgb_l2len(msg), msgb_hexdump_l2(msg)); + + /* distribute or drop */ + if (ms->l1_entity.l1_gprs_ul_block_cnf) + return ms->l1_entity.l1_gprs_ul_block_cnf(ms, msg); + + msgb_free(msg); + return 0; +} + /* Receive L1CTL_GPRS_DL_BLOCK_IND */ static int rx_l1_gprs_dl_block_ind(struct osmocom_ms *ms, struct msgb *msg) { @@ -1171,6 +1201,9 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg) case L1CTL_TRAFFIC_CONF: msgb_free(msg); break; + case L1CTL_GPRS_UL_BLOCK_CNF: + rc = rx_l1_gprs_ul_block_cnf(ms, msg); + break; case L1CTL_GPRS_DL_BLOCK_IND: rc = rx_l1_gprs_dl_block_ind(ms, msg); break; diff --git a/src/host/layer23/src/modem/grr.c b/src/host/layer23/src/modem/grr.c index cbabdc9a0..cd325c4c6 100644 --- a/src/host/layer23/src/modem/grr.c +++ b/src/host/layer23/src/modem/grr.c @@ -521,6 +521,18 @@ static void handle_pdch_establish_req(struct osmo_fsm_inst *fi, osmo_fsm_inst_state_chg(fi, GRR_ST_PACKET_TRANSFER, 0, 0); } +static void handle_pdch_block_cnf(struct osmocom_ms *ms, struct msgb *msg) +{ + const struct l1ctl_gprs_ul_block_cnf *cnf = (void *)msg->l1h; + const uint32_t fn = osmo_load32be(&cnf->fn); + struct osmo_gprs_rlcmac_prim *prim; + + prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_cnf(cnf->tn, fn, + msgb_l2(msg), + msgb_l2len(msg)); + osmo_gprs_rlcmac_prim_lower_up(prim); +} + static void handle_pdch_block_ind(struct osmocom_ms *ms, struct msgb *msg) { const struct l1ctl_gprs_dl_block_ind *ind = (void *)msg->l1h; @@ -753,6 +765,9 @@ static void grr_st_packet_transfer_action(struct osmo_fsm_inst *fi, lp->pdch_data_req.data_len); break; } + case GRR_EV_PDCH_BLOCK_CNF: + handle_pdch_block_cnf(ms, (struct msgb *)data); + break; case GRR_EV_PDCH_BLOCK_IND: handle_pdch_block_ind(ms, (struct msgb *)data); break; @@ -819,6 +834,7 @@ static const struct osmo_fsm_state grr_fsm_states[] = { .in_event_mask = S(GRR_EV_PDCH_UL_TBF_CFG_REQ) | S(GRR_EV_PDCH_DL_TBF_CFG_REQ) | S(GRR_EV_PDCH_BLOCK_REQ) + | S(GRR_EV_PDCH_BLOCK_CNF) | S(GRR_EV_PDCH_BLOCK_IND) | S(GRR_EV_PDCH_RTS_IND) | S(GRR_EV_PDCH_RELEASE_REQ), @@ -838,6 +854,7 @@ static const struct value_string grr_fsm_event_names[] = { OSMO_VALUE_STRING(GRR_EV_PDCH_UL_TBF_CFG_REQ), OSMO_VALUE_STRING(GRR_EV_PDCH_DL_TBF_CFG_REQ), OSMO_VALUE_STRING(GRR_EV_PDCH_BLOCK_REQ), + OSMO_VALUE_STRING(GRR_EV_PDCH_BLOCK_CNF), OSMO_VALUE_STRING(GRR_EV_PDCH_BLOCK_IND), OSMO_VALUE_STRING(GRR_EV_PDCH_RTS_IND), { 0, NULL } diff --git a/src/host/layer23/src/modem/rlcmac.c b/src/host/layer23/src/modem/rlcmac.c index a9588f7aa..7f7b5661d 100644 --- a/src/host/layer23/src/modem/rlcmac.c +++ b/src/host/layer23/src/modem/rlcmac.c @@ -162,12 +162,17 @@ static int modem_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *prim, void *u } } -static int l1ctl_dl_block_cb(struct osmocom_ms *ms, struct msgb *msg) +static int l1ctl_ul_block_cnf_cb(struct osmocom_ms *ms, struct msgb *msg) +{ + return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_PDCH_BLOCK_CNF, msg); +} + +static int l1ctl_dl_block_ind_cb(struct osmocom_ms *ms, struct msgb *msg) { return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_PDCH_BLOCK_IND, msg); } -static int l1ctl_rts_cb(struct osmocom_ms *ms, struct msgb *msg) +static int l1ctl_rts_ind_cb(struct osmocom_ms *ms, struct msgb *msg) { return osmo_fsm_inst_dispatch(ms->grr_fi, GRR_EV_PDCH_RTS_IND, msg); } @@ -186,8 +191,9 @@ int modem_rlcmac_init(struct osmocom_ms *ms) osmo_gprs_rlcmac_prim_set_up_cb(modem_rlcmac_prim_up_cb, ms); osmo_gprs_rlcmac_prim_set_down_cb(modem_rlcmac_prim_down_cb, ms); - ms->l1_entity.l1_gprs_dl_block_ind = &l1ctl_dl_block_cb; - ms->l1_entity.l1_gprs_rts_ind = &l1ctl_rts_cb; + ms->l1_entity.l1_gprs_ul_block_cnf = &l1ctl_ul_block_cnf_cb; + ms->l1_entity.l1_gprs_dl_block_ind = &l1ctl_dl_block_ind_cb; + ms->l1_entity.l1_gprs_rts_ind = &l1ctl_rts_ind_cb; return rc; }