aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/gsm_data.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2021-04-24 14:48:19 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2021-06-10 16:15:35 +0200
commitd163aa380588bb8628c45d7ce34838595dc6e1f2 (patch)
treefd3d33492be42dac286977fc9a3866a4fb7f88e0 /src/osmo-bsc/gsm_data.c
parent52a6b2cebfb3aba0f631c6121361b8d07318984b (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.c69
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;