diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2016-06-13 15:03:18 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-06-15 09:30:24 +0000 |
commit | 7158c2ed082eaca6063a501e490e8d3c3b181560 (patch) | |
tree | 69af1124768459a67afe6cc2a93f8344aa8e6777 /src | |
parent | a55b166c6c7af79cbefe8e65fe77b2d61c634d2d (diff) |
sysmo: add L3 handle to l1prim messages
Place a layer 3 handle into GSM L1 messages to better match up confirmations to
respective requests. This handle is a uint32_t transparently returned in the
confirmation messages, so a match-up is easy to add.
So far, a GSM L1 confirmation message received for a preceding L1 Request was
matched only by the prim_id. That meant that only one instance of the same
primitive could be waiting for a confirmation at any given time, or the
responses would get mixed up: the struct wait_l1_conf instances entered into
the fl1h->wlc_list queue would be returned to a possibly mismatching
confirmation handler. (Seen during testing of dyn pdch switching.)
Send the hLayer3 handle out via prim_init(), using new static functions to
produce handles on different scopes:
* l1p_handle_for_trx()
* l1p_handle_for_ts()
* l1p_handle_for_lchan()
(These could possibly move to a more general .h/.c file later.)
Remember the hLayer3 handle in
* struct wait_l1_conf.
Match the incoming confirmations' and stored hLayer3 handles up in, and remove
a now obsolete comment from:
* is_prim_compat()
Since the hLayer3 members are at different byte offsets in
GsmL1_Prim_t.u.*, use large switch statements to set/get the value:
* In prim_init(), extend existing switch statement to set in GsmL1_Prim_t.
* Add l1p_get_hLayer3() to retrieve from GsmL1_Prim_t (could possibly move to a
more general .h/.c file later).
Change-Id: Ie4533c6cbc160318917e7a672ab6f9a848f01d1b
Diffstat (limited to 'src')
-rw-r--r-- | src/osmo-bts-sysmo/l1_if.c | 58 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/oml.c | 83 |
2 files changed, 128 insertions, 13 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c index 84fad994..14de251e 100644 --- a/src/osmo-bts-sysmo/l1_if.c +++ b/src/osmo-bts-sysmo/l1_if.c @@ -67,6 +67,7 @@ struct wait_l1_conf { struct llist_head list; /* internal linked list */ struct osmo_timer_list timer; /* timer for L1 timeout */ unsigned int conf_prim_id; /* primitive we expect in response */ + HANDLE conf_hLayer3; /* layer 3 handle we expect in response */ unsigned int is_sys_prim; /* is this a system (1) or L1 (0) primitive */ l1if_compl_cb *cb; void *cb_data; @@ -91,6 +92,58 @@ static void l1if_req_timeout(void *data) exit(23); } +static HANDLE l1p_get_hLayer3(GsmL1_Prim_t *prim) +{ + switch (prim->id) { + case GsmL1_PrimId_MphInitReq: + return prim->u.mphInitReq.hLayer3; + case GsmL1_PrimId_MphCloseReq: + return prim->u.mphCloseReq.hLayer3; + case GsmL1_PrimId_MphConnectReq: + return prim->u.mphConnectReq.hLayer3; + case GsmL1_PrimId_MphDisconnectReq: + return prim->u.mphDisconnectReq.hLayer3; + case GsmL1_PrimId_MphActivateReq: + return prim->u.mphActivateReq.hLayer3; + case GsmL1_PrimId_MphDeactivateReq: + return prim->u.mphDeactivateReq.hLayer3; + case GsmL1_PrimId_MphConfigReq: + return prim->u.mphConfigReq.hLayer3; + case GsmL1_PrimId_MphMeasureReq: + return prim->u.mphMeasureReq.hLayer3; + case GsmL1_PrimId_MphInitCnf: + return prim->u.mphInitCnf.hLayer3; + case GsmL1_PrimId_MphCloseCnf: + return prim->u.mphCloseCnf.hLayer3; + case GsmL1_PrimId_MphConnectCnf: + return prim->u.mphConnectCnf.hLayer3; + case GsmL1_PrimId_MphDisconnectCnf: + return prim->u.mphDisconnectCnf.hLayer3; + case GsmL1_PrimId_MphActivateCnf: + return prim->u.mphActivateCnf.hLayer3; + case GsmL1_PrimId_MphDeactivateCnf: + return prim->u.mphDeactivateCnf.hLayer3; + case GsmL1_PrimId_MphConfigCnf: + return prim->u.mphConfigCnf.hLayer3; + case GsmL1_PrimId_MphMeasureCnf: + return prim->u.mphMeasureCnf.hLayer3; + case GsmL1_PrimId_MphTimeInd: + case GsmL1_PrimId_MphSyncInd: + case GsmL1_PrimId_PhEmptyFrameReq: + case GsmL1_PrimId_PhDataReq: + case GsmL1_PrimId_PhConnectInd: + case GsmL1_PrimId_PhReadyToSendInd: + case GsmL1_PrimId_PhDataInd: + case GsmL1_PrimId_PhRaInd: + break; + default: + LOGP(DL1C, LOGL_ERROR, "unknown L1 primitive %u\n", prim->id); + break; + } + return 0; +} + + static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, int is_system_prim, l1if_compl_cb *cb, void *data) { @@ -118,6 +171,7 @@ static int _l1if_req_compl(struct femtol1_hdl *fl1h, struct msgb *msg, } wlc->is_sys_prim = 0; wlc->conf_prim_id = femtobts_l1prim_req2conf[l1p->id]; + wlc->conf_hLayer3 = l1p_get_hLayer3(l1p); wqueue = &fl1h->write_q[MQ_L1_WRITE]; timeout_secs = 30; } else { @@ -943,12 +997,12 @@ static int l1if_handle_ind(struct femtol1_hdl *fl1, struct msgb *msg) static inline int is_prim_compat(GsmL1_Prim_t *l1p, struct wait_l1_conf *wlc) { - /* the limitation here is that we cannot have multiple callers - * sending the same primitive */ if (wlc->is_sys_prim != 0) return 0; if (l1p->id != wlc->conf_prim_id) return 0; + if (l1p_get_hLayer3(l1p) != wlc->conf_hLayer3) + return 0; return 1; } diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c index cd03b22d..6951f84b 100644 --- a/src/osmo-bts-sysmo/oml.c +++ b/src/osmo-bts-sysmo/oml.c @@ -92,45 +92,70 @@ static const enum GsmL1_LogChComb_t pchan_to_logChComb[_GSM_PCHAN_MAX] = { static int trx_rf_lock(struct gsm_bts_trx *trx, int locked, l1if_compl_cb *cb); -static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl *gl1) +static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl *gl1, + HANDLE hLayer3) { prim->id = id; - /* for some reason the hLayer1 field is not always at the same position - * in the GsmL1_Prim_t, so we have to have this ugly case statement here... */ + /* for some reason the hLayer1 and hlayer3 fields are not always at the + * same position in the GsmL1_Prim_t, so we have to have this ugly case + * statement here... */ switch (id) { case GsmL1_PrimId_MphInitReq: //prim->u.mphInitReq.hLayer1 = gl1->hLayer1; + prim->u.mphInitReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphCloseReq: prim->u.mphCloseReq.hLayer1 = gl1->hLayer1; + prim->u.mphCloseReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphConnectReq: prim->u.mphConnectReq.hLayer1 = gl1->hLayer1; + prim->u.mphConnectReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphDisconnectReq: prim->u.mphDisconnectReq.hLayer1 = gl1->hLayer1; + prim->u.mphDisconnectReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphActivateReq: prim->u.mphActivateReq.hLayer1 = gl1->hLayer1; + prim->u.mphActivateReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphDeactivateReq: prim->u.mphDeactivateReq.hLayer1 = gl1->hLayer1; + prim->u.mphDeactivateReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphConfigReq: prim->u.mphConfigReq.hLayer1 = gl1->hLayer1; + prim->u.mphConfigReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphMeasureReq: prim->u.mphMeasureReq.hLayer1 = gl1->hLayer1; + prim->u.mphMeasureReq.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphInitCnf: + prim->u.mphInitCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphCloseCnf: + prim->u.mphCloseCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphConnectCnf: + prim->u.mphConnectCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphDisconnectCnf: + prim->u.mphDisconnectCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphActivateCnf: + prim->u.mphActivateCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphDeactivateCnf: + prim->u.mphDeactivateCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphConfigCnf: + prim->u.mphConfigCnf.hLayer3 = hLayer3; + break; case GsmL1_PrimId_MphMeasureCnf: + prim->u.mphMeasureCnf.hLayer3 = hLayer3; break; case GsmL1_PrimId_MphTimeInd: break; @@ -157,6 +182,35 @@ static void *prim_init(GsmL1_Prim_t *prim, GsmL1_PrimId_t id, struct femtol1_hdl return &prim->u; } +static HANDLE l1p_handle_for_trx(struct gsm_bts_trx *trx) +{ + struct gsm_bts *bts = trx->bts; + + osmo_static_assert(sizeof(HANDLE) >= 4, l1p_handle_is_at_least_32bit); + osmo_static_assert(sizeof(trx->nr) == 1, trx_nr_is_8bit); + osmo_static_assert(sizeof(bts->nr) == 1, bts_nr_is_8bit); + + return bts->nr << 24 + | trx->nr << 16; +} + +static HANDLE l1p_handle_for_ts(struct gsm_bts_trx_ts *ts) +{ + osmo_static_assert(sizeof(ts->nr) == 1, ts_nr_is_8bit); + + return l1p_handle_for_trx(ts->trx) + | ts->nr << 8; +} + + +static HANDLE l1p_handle_for_lchan(struct gsm_lchan *lchan) +{ + osmo_static_assert(sizeof(lchan->nr) == 1, lchan_nr_is_8bit); + + return l1p_handle_for_ts(lchan->ts) + | lchan->nr; +} + GsmL1_Status_t prim_status(GsmL1_Prim_t *prim) { /* for some reason the Status field is not always at the same position @@ -346,7 +400,8 @@ static int trx_init(struct gsm_bts_trx *trx) } msg = l1p_msgb_alloc(); - mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h); + mi_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphInitReq, fl1h, + l1p_handle_for_trx(trx)); dev_par = &mi_req->deviceParam; dev_par->devType = GsmL1_DevType_TxdRxu; dev_par->freqBand = femto_band; @@ -385,7 +440,8 @@ int bts_model_trx_close(struct gsm_bts_trx *trx) struct msgb *msg; msg = l1p_msgb_alloc(); - prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h); + prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphCloseReq, fl1h, + l1p_handle_for_trx(trx)); LOGP(DL1C, LOGL_NOTICE, "Close TRX %u\n", trx->nr); return l1if_gsm_req_compl(fl1h, msg, trx_close_compl_cb, NULL); @@ -430,7 +486,8 @@ static int ts_connect(struct gsm_bts_trx_ts *ts) struct femtol1_hdl *fl1h = trx_femtol1_hdl(ts->trx); GsmL1_MphConnectReq_t *cr; - cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h); + cr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConnectReq, fl1h, + l1p_handle_for_ts(ts)); cr->u8Tn = ts->nr; cr->logChComb = pchan_to_logChComb[ts->pchan]; @@ -917,7 +974,8 @@ static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd) GsmL1_MphActivateReq_t *act_req; GsmL1_LogChParam_t *lch_par; - act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, fl1h); + act_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphActivateReq, + fl1h, l1p_handle_for_lchan(lchan)); lch_par = &act_req->logChPrm; act_req->u8Tn = lchan->ts->nr; act_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); @@ -1210,7 +1268,8 @@ static int mph_send_config_logchpar(struct gsm_lchan *lchan, struct sapi_cmd *cm /* channel mode, encryption and/or multirate have changed */ /* update multi-rate config */ - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h); + conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, + l1p_handle_for_lchan(lchan)); conf_req->cfgParamId = GsmL1_ConfigParamId_SetLogChParams; conf_req->cfgParams.setLogChParams.sapi = cmd->sapi; conf_req->cfgParams.setLogChParams.u8Tn = lchan->ts->nr; @@ -1263,7 +1322,7 @@ int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power) struct msgb *msg = l1p_msgb_alloc(); GsmL1_MphConfigReq_t *conf_req; - conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h); + conf_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, 0); conf_req->cfgParamId = GsmL1_ConfigParamId_SetTxPowerLevel; conf_req->cfgParams.setTxPowerLevel.fTxPowerLevel = tx_power; @@ -1284,7 +1343,8 @@ static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *c struct msgb *msg = l1p_msgb_alloc(); struct GsmL1_MphConfigReq_t *cfgr; - cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h); + cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h, + l1p_handle_for_lchan(lchan)); cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams; cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr; @@ -1431,7 +1491,8 @@ static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd struct msgb *msg = l1p_msgb_alloc(); GsmL1_MphDeactivateReq_t *deact_req; - deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, fl1h); + deact_req = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphDeactivateReq, + fl1h, l1p_handle_for_lchan(lchan)); deact_req->u8Tn = lchan->ts->nr; deact_req->subCh = lchan_to_GsmL1_SubCh_t(lchan); deact_req->dir = cmd->dir; |