diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2021-04-24 14:48:19 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2021-06-10 16:15:35 +0200 |
commit | d163aa380588bb8628c45d7ce34838595dc6e1f2 (patch) | |
tree | fd3d33492be42dac286977fc9a3866a4fb7f88e0 /src/osmo-bsc/gsm_data.c | |
parent | 52a6b2cebfb3aba0f631c6121361b8d07318984b (diff) |
add VAMOS secondary lchans to timeslot struct
So far there is a bunch of code setting a primary lchan in VAMOS mode.
This patch now adds the actual secondary "shadow" lchans that may be
combined with a primary lchan in VAMOS mode to form a multiplex.
VAMOS lchans are put in the same ts->lchan[] array that keeps the
primary lchans. They are at most two additional usable lchans (for a
TCH/H shadow) added to either TCH/F or TCH/H.
Keeping these in the same array allows looping over all lchans easily.
The ts->max_primary_lchans indicates the index of the first VAMOS shadow
lchan.
Related: SYS#5315 OS#4940
Change-Id: I928af99498bba488d317693f3144d4fccbbe9af3
Diffstat (limited to 'src/osmo-bsc/gsm_data.c')
-rw-r--r-- | src/osmo-bsc/gsm_data.c | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index b33b1c39d..4d2d81181 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -337,8 +337,9 @@ char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts) char *gsm_lchan_name_compute(void *ctx, const struct gsm_lchan *lchan) { struct gsm_bts_trx_ts *ts = lchan->ts; - return talloc_asprintf(ctx, "(bts=%d,trx=%d,ts=%d,ss=%d)", - ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr); + return talloc_asprintf(ctx, "(bts=%d,trx=%d,ts=%d,ss=%d%s)", + ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr, + lchan->vamos.is_secondary ? "-VAMOS" : ""); } /* obtain the MO structure for a given object instance */ @@ -545,9 +546,13 @@ uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan, uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan) { - /* Note: non-standard Osmocom style dyn TS PDCH mode chan_nr is only used within - * rsl_tx_dyn_ts_pdch_act_deact(). */ - return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan->nr); + uint8_t lchan_nr = lchan->nr; + /* The VAMOS lchans are behind the primary ones in the ts->lchan[] array. They keep their lchan->nr as in the + * array, but on the wire they are the "shadow" lchans for the primary lchans. For example, for TCH/F, there is + * a primary ts->lchan[0] and a VAMOS ts->lchan[1]. Still, the VAMOS lchan should send chan_nr = 0. */ + if (lchan->vamos.is_secondary) + lchan_nr -= lchan->ts->max_primary_lchans; + return gsm_pchan2chan_nr(lchan->ts->pchan_is, lchan->ts->nr, lchan_nr); } static const uint8_t subslots_per_pchan[] = { @@ -574,6 +579,30 @@ uint8_t pchan_subslots(enum gsm_phys_chan_config pchan) return subslots_per_pchan[pchan]; } +static const uint8_t subslots_per_pchan_vamos[] = { + [GSM_PCHAN_NONE] = 0, + [GSM_PCHAN_CCCH] = 0, + [GSM_PCHAN_PDCH] = 0, + [GSM_PCHAN_CCCH_SDCCH4] = 0, + /* VAMOS: on a TCH/F, there may be a TCH/H shadow */ + [GSM_PCHAN_TCH_F] = 2, + [GSM_PCHAN_TCH_H] = 2, + [GSM_PCHAN_SDCCH8_SACCH8C] = 0, + [GSM_PCHAN_CCCH_SDCCH4_CBCH] = 0, + [GSM_PCHAN_SDCCH8_SACCH8C_CBCH] = 0, + [GSM_PCHAN_TCH_F_TCH_H_PDCH] = 2, + [GSM_PCHAN_TCH_F_PDCH] = 2, +}; + +/* Return the maximum number of VAMOS secondary lchans that may be used in a timeslot of the given physical channel + * configuration. */ +uint8_t pchan_subslots_vamos(enum gsm_phys_chan_config pchan) +{ + if (pchan < 0 || pchan >= ARRAY_SIZE(subslots_per_pchan_vamos)) + return 0; + return subslots_per_pchan_vamos[pchan]; +} + static bool pchan_is_tch(enum gsm_phys_chan_config pchan) { switch (pchan) { @@ -590,6 +619,36 @@ bool ts_is_tch(struct gsm_bts_trx_ts *ts) return pchan_is_tch(ts->pchan_is); } +/* For a VAMOS secondary shadow lchan, return its primary lchan. If the lchan is not a secondary lchan, return NULL. */ +struct gsm_lchan *gsm_lchan_vamos_to_primary(const struct gsm_lchan *lchan_vamos) +{ + struct gsm_lchan *lchan_primary; + if (!lchan_vamos || !lchan_vamos->vamos.is_secondary) + return NULL; + /* OsmoBSC currently does not support mixed TCH/F + TCH/H VAMOS multiplexes. Hence the primary <-> secondary + * relation is a simple index shift in the lchan array. If mixed multiplexes were allowed, a TCH/F primary might + * have two TCH/H VAMOS secondary lchans, etc. Fortunately, we don't need to care about that. */ + lchan_primary = (struct gsm_lchan*)lchan_vamos - lchan_vamos->ts->max_primary_lchans; + if (!lchan_primary->fi) + return NULL; + return lchan_primary; +} + +/* For a primary lchan, return its VAMOS secondary shadow lchan. If the lchan is not a primary lchan, return NULL. */ +struct gsm_lchan *gsm_lchan_primary_to_vamos(const struct gsm_lchan *lchan_primary) +{ + struct gsm_lchan *lchan_vamos; + if (!lchan_primary || lchan_primary->vamos.is_secondary) + return NULL; + /* OsmoBSC currently does not support mixed TCH/F + TCH/H VAMOS multiplexes. Hence the primary <-> secondary + * relation is a simple index shift in the lchan array. If mixed multiplexes were allowed, a TCH/F primary might + * have two TCH/H VAMOS secondary lchans, etc. Fortunately, we don't need to care about that. */ + lchan_vamos = (struct gsm_lchan*)lchan_primary + lchan_primary->ts->max_primary_lchans; + if (!lchan_vamos->fi) + return NULL; + return lchan_vamos; +} + struct gsm_bts *conn_get_bts(struct gsm_subscriber_connection *conn) { if (!conn || !conn->lchan) return NULL; |