aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2016-06-13 15:03:18 +0200
committerHarald Welte <laforge@gnumonks.org>2016-06-15 09:30:24 +0000
commit7158c2ed082eaca6063a501e490e8d3c3b181560 (patch)
tree69af1124768459a67afe6cc2a93f8344aa8e6777
parenta55b166c6c7af79cbefe8e65fe77b2d61c634d2d (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
-rw-r--r--src/osmo-bts-sysmo/l1_if.c58
-rw-r--r--src/osmo-bts-sysmo/oml.c83
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;