Change in osmo-bts[master]: [VAMOS] Implement the concept of 'shadow' timeslots

fixeria gerrit-no-reply at lists.osmocom.org
Sun Jun 6 01:09:26 UTC 2021


fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/24153 )

Change subject: [VAMOS] Implement the concept of 'shadow' timeslots
......................................................................

[VAMOS] Implement the concept of 'shadow' timeslots

Change-Id: I48b44b4df9ffb1cca105aebbd868c29b21f3b1d6
Depends: Ia0bd8695a3f12331b696fe69117189cdd48b584d
Related: SYS#4895, OS#4941
---
M include/osmo-bts/bts_trx.h
M include/osmo-bts/gsm_data.h
M include/osmo-bts/l1sap.h
M src/common/bts_trx.c
M src/common/gsm_data.c
M src/common/l1sap.c
M src/common/oml.c
M src/common/scheduler.c
M src/common/vty.c
9 files changed, 218 insertions(+), 68 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve



diff --git a/include/osmo-bts/bts_trx.h b/include/osmo-bts/bts_trx.h
index d4c3f39..f033573 100644
--- a/include/osmo-bts/bts_trx.h
+++ b/include/osmo-bts/bts_trx.h
@@ -48,6 +48,7 @@
 
 struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
 struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
+void gsm_bts_trx_init_shadow_ts(struct gsm_bts_trx *trx);
 char *gsm_trx_name(const struct gsm_bts_trx *trx);
 const char *gsm_trx_unit_id(struct gsm_bts_trx *trx);
 
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 93eb2f0..6ce5c3b 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -463,6 +463,13 @@
 	/* Implementation specific structure(s) */
 	void *priv;
 
+	/* VAMOS specific fields */
+	struct {
+		/* NULL if BTS_FEAT_VAMOS is not set */
+		struct gsm_bts_trx_ts *peer;
+		bool is_shadow;
+	} vamos;
+
 	struct gsm_lchan lchan[TS_MAX_LCHAN];
 };
 
@@ -515,6 +522,12 @@
 void gsm_lchan_name_update(struct gsm_lchan *lchan);
 const char *gsm_lchans_name(enum gsm_lchan_state s);
 
+#define GSM_TS_NAME_FMT \
+	"bts=%u,trx=%u,ts=%u" "%s"
+#define GSM_TS_NAME_ARGS(ts) \
+	(ts)->trx->bts->nr, (ts)->trx->nr, (ts)->nr, \
+	(ts)->vamos.is_shadow ? ",shadow" : ""
+
 static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
 {
 	return lchan->name;
diff --git a/include/osmo-bts/l1sap.h b/include/osmo-bts/l1sap.h
index fe77431..f78d114 100644
--- a/include/osmo-bts/l1sap.h
+++ b/include/osmo-bts/l1sap.h
@@ -19,9 +19,11 @@
 #define L1SAP_IS_LINK_SACCH(link_id) \
 	((link_id & 0xC0) == LID_SACCH)
 #define L1SAP_IS_CHAN_TCHF(chan_nr) \
-	((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs)
+	((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs || \
+	 (chan_nr & 0xf8) == RSL_CHAN_OSMO_VAMOS_Bm_ACCHs)
 #define L1SAP_IS_CHAN_TCHH(chan_nr) \
-	((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs)
+	((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs || \
+	 (chan_nr & 0xf0) == RSL_CHAN_OSMO_VAMOS_Lm_ACCHs)
 #define L1SAP_IS_CHAN_SDCCH4(chan_nr) \
 	((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH)
 #define L1SAP_IS_CHAN_SDCCH8(chan_nr) \
@@ -37,6 +39,9 @@
 #define L1SAP_IS_CHAN_CBCH(chan_nr) \
 	((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH4) \
 	|| ((chan_nr & 0xf8) == RSL_CHAN_OSMO_CBCH8)
+#define L1SAP_IS_CHAN_VAMOS(chan_nr) \
+	((chan_nr & 0xf8) == RSL_CHAN_OSMO_VAMOS_Bm_ACCHs || \
+	 (chan_nr & 0xf0) == RSL_CHAN_OSMO_VAMOS_Lm_ACCHs)
 
 /* rach type from ra */
 #define L1SAP_IS_PACKET_RACH(ra) ((ra & 0xf0) == 0x70 && (ra & 0x0f) != 0x0f)
diff --git a/src/common/bts_trx.c b/src/common/bts_trx.c
index 3d295e5..a5d7ed3 100644
--- a/src/common/bts_trx.c
+++ b/src/common/bts_trx.c
@@ -1,5 +1,5 @@
 /* (C) 2008-2010 by Harald Welte <laforge at gnumonks.org>
- * (C) 2020 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de>
+ * (C) 2020-2021 by sysmocom - s.f.m.c. GmbH <info at sysmocom.de>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -52,10 +52,76 @@
 	return 0;
 }
 
+/* Initialize all logical channels of the given timeslot */
+static void gsm_bts_trx_ts_init_lchan(struct gsm_bts_trx_ts *ts)
+{
+	unsigned int ln;
+
+	for (ln = 0; ln < ARRAY_SIZE(ts->lchan); ln++) {
+		struct gsm_lchan *lchan = &ts->lchan[ln];
+
+		lchan->ts = ts;
+		lchan->nr = ln;
+		lchan->type = GSM_LCHAN_NONE;
+		gsm_lchan_name_update(lchan);
+
+		INIT_LLIST_HEAD(&lchan->sapi_cmds);
+		INIT_LLIST_HEAD(&lchan->dl_tch_queue);
+	}
+}
+
+/* Initialize primary timeslots of the given transceiver */
+static void gsm_bts_trx_init_ts(struct gsm_bts_trx *trx)
+{
+	unsigned int tn;
+
+	for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+		struct gsm_bts_trx_ts *ts = &trx->ts[tn];
+
+		ts->trx = trx;
+		ts->nr = tn;
+
+		ts->mo.fi = osmo_fsm_inst_alloc(&nm_chan_fsm, trx, ts,
+						LOGL_INFO, NULL);
+		osmo_fsm_inst_update_id_f(ts->mo.fi, "%s-ts%u",
+					  trx->bb_transc.mo.fi->id, ts->nr);
+		gsm_mo_init(&ts->mo, trx->bts, NM_OC_CHANNEL,
+			    trx->bts->nr, trx->nr, ts->nr);
+
+		gsm_bts_trx_ts_init_lchan(ts);
+	}
+}
+
+/* Initialize shadow timeslots of the given transceiver */
+void gsm_bts_trx_init_shadow_ts(struct gsm_bts_trx *trx)
+{
+	unsigned int tn;
+
+	for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++) {
+		struct gsm_bts_trx_ts *ts;
+
+		ts = talloc_zero(trx, struct gsm_bts_trx_ts);
+		OSMO_ASSERT(ts != NULL);
+
+		ts->trx = trx;
+		ts->nr = tn;
+
+		/* Link both primary and shadow */
+		trx->ts[tn].vamos.peer = ts;
+		ts->vamos.peer = &trx->ts[tn];
+		ts->vamos.is_shadow = true;
+
+		/* Shadow timeslot uses the primary's NM FSM */
+		OSMO_ASSERT(trx->ts[tn].mo.fi != NULL);
+		ts->mo.fi = trx->ts[tn].mo.fi;
+
+		gsm_bts_trx_ts_init_lchan(ts);
+	}
+}
+
 struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
 {
 	struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
-	int k;
 
 	if (!trx)
 		return NULL;
@@ -77,36 +143,7 @@
 	gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC,
 		    bts->nr, trx->nr, 0xff);
 
-	for (k = 0; k < TRX_NR_TS; k++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[k];
-		int l;
-
-		ts->trx = trx;
-		ts->nr = k;
-		ts->pchan = GSM_PCHAN_NONE;
-		ts->dyn.pchan_is = GSM_PCHAN_NONE;
-		ts->dyn.pchan_want = GSM_PCHAN_NONE;
-
-		ts->mo.fi = osmo_fsm_inst_alloc(&nm_chan_fsm, trx, ts,
-						     LOGL_INFO, NULL);
-		osmo_fsm_inst_update_id_f(ts->mo.fi, "bts%d-trx%d-ts%d",
-					  bts->nr, trx->nr, ts->nr);
-		gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL,
-			    bts->nr, trx->nr, ts->nr);
-
-		for (l = 0; l < TS_MAX_LCHAN; l++) {
-			struct gsm_lchan *lchan;
-			lchan = &ts->lchan[l];
-
-			lchan->ts = ts;
-			lchan->nr = l;
-			lchan->type = GSM_LCHAN_NONE;
-			gsm_lchan_name_update(lchan);
-
-			INIT_LLIST_HEAD(&lchan->sapi_cmds);
-			INIT_LLIST_HEAD(&lchan->dl_tch_queue);
-		}
-	}
+	gsm_bts_trx_init_ts(trx);
 
 	if (trx->nr != 0)
 		trx->nominal_power = bts->c0->nominal_power;
diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c
index 6328783..09664e2 100644
--- a/src/common/gsm_data.c
+++ b/src/common/gsm_data.c
@@ -107,11 +107,11 @@
 
 static char ts2str[255];
 
-
 char *gsm_ts_name(const struct gsm_bts_trx_ts *ts)
 {
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
-		 ts->trx->bts->nr, ts->trx->nr, ts->nr);
+	snprintf(ts2str, sizeof(ts2str),
+		 "(" GSM_TS_NAME_FMT ")",
+		 GSM_TS_NAME_ARGS(ts));
 
 	return ts2str;
 }
@@ -123,15 +123,14 @@
 	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
 		if (ts->dyn.pchan_is == ts->dyn.pchan_want)
 			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
+				 "(" GSM_TS_NAME_FMT ",pchan=%s as %s)",
+				 GSM_TS_NAME_ARGS(ts),
 				 gsm_pchan_name(ts->pchan),
 				 gsm_pchan_name(ts->dyn.pchan_is));
 		else
 			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s"
-				 " switching %s -> %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
+				 "(" GSM_TS_NAME_FMT ",pchan=%s switching %s -> %s)",
+				 GSM_TS_NAME_ARGS(ts),
 				 gsm_pchan_name(ts->pchan),
 				 gsm_pchan_name(ts->dyn.pchan_is),
 				 gsm_pchan_name(ts->dyn.pchan_want));
@@ -139,16 +138,15 @@
 	case GSM_PCHAN_TCH_F_PDCH:
 		if ((ts->flags & TS_F_PDCH_PENDING_MASK) == 0)
 			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s as %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
+				 "(" GSM_TS_NAME_FMT ",pchan=%s as %s)",
+				 GSM_TS_NAME_ARGS(ts),
 				 gsm_pchan_name(ts->pchan),
 				 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
 							       : "TCH/F");
 		else
 			snprintf(ts2str, sizeof(ts2str),
-				 "(bts=%d,trx=%d,ts=%d,pchan=%s"
-				 " switching %s -> %s)",
-				 ts->trx->bts->nr, ts->trx->nr, ts->nr,
+				 "(" GSM_TS_NAME_FMT ",pchan=%s switching %s -> %s)",
+				 GSM_TS_NAME_ARGS(ts),
 				 gsm_pchan_name(ts->pchan),
 				 (ts->flags & TS_F_PDCH_ACTIVE)? "PDCH"
 							       : "TCH/F",
@@ -156,9 +154,8 @@
 								    : "TCH/F");
 		break;
 	default:
-		snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,pchan=%s)",
-			 ts->trx->bts->nr, ts->trx->nr, ts->nr,
-			 gsm_pchan_name(ts->pchan));
+		snprintf(ts2str, sizeof(ts2str), "(" GSM_TS_NAME_FMT ",pchan=%s)",
+			 GSM_TS_NAME_ARGS(ts), gsm_pchan_name(ts->pchan));
 		break;
 	}
 
@@ -171,8 +168,8 @@
 	const struct gsm_bts_trx *trx = ts->trx;
 	char *name;
 
-	name = talloc_asprintf(trx, "(bts=%u,trx=%u,ts=%u,ss=%u)",
-			       trx->bts->nr, trx->nr, ts->nr, lchan->nr);
+	name = talloc_asprintf(trx, "(" GSM_TS_NAME_FMT ",ss=%u)",
+			       GSM_TS_NAME_ARGS(ts), lchan->nr);
 	if (lchan->name != NULL)
 		talloc_free(lchan->name);
 	lchan->name = name;
@@ -248,19 +245,30 @@
 
 uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan)
 {
+	uint8_t chan_nr;
+
 	switch (lchan->ts->pchan) {
 	case GSM_PCHAN_TCH_F_TCH_H_PDCH:
 		/* Return chan_nr reflecting the current TS pchan, either a standard TCH kind, or the
 		 * nonstandard value reflecting PDCH for Osmocom style dyn TS. */
-		return gsm_lchan_as_pchan2chan_nr(lchan,
-						  lchan->ts->dyn.pchan_is);
+		chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, lchan->ts->dyn.pchan_is);
+		break;
 	case GSM_PCHAN_TCH_F_PDCH:
 		/* For ip.access style dyn TS, we always want to use the chan_nr as if it was TCH/F.
 		 * We're using custom PDCH ACT and DEACT messages that use the usual chan_nr values. */
-		return gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F);
+		chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F);
+		break;
 	default:
-		return gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
+		chan_nr = gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr);
+		break;
 	}
+
+	/* VAMOS: if this lchan belongs to a shadow timeslot, we must reflect
+	 * this in the channel number.  Convert it to Osmocom specific value. */
+	if (lchan->ts->vamos.is_shadow)
+		chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK;
+
+	return chan_nr;
 }
 
 uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
@@ -286,6 +294,11 @@
 		*rc = -EINVAL;
 
 	switch (cbits) {
+	case ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Bm_ACCHs:
+		if (ts->vamos.peer == NULL)
+			return NULL;
+		ts = ts->vamos.peer;
+		/* fall-through */
 	case ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs:
 		lch_idx = 0;	/* TCH/F */
 		if (ts->pchan != GSM_PCHAN_TCH_F &&
@@ -294,6 +307,12 @@
 		    ts->pchan != GSM_PCHAN_TCH_F_TCH_H_PDCH)
 			ok = false;
 		break;
+	case ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Lm_ACCHs(0):
+	case ABIS_RSL_CHAN_NR_CBITS_OSMO_VAMOS_Lm_ACCHs(1):
+		if (ts->vamos.peer == NULL)
+			return NULL;
+		ts = ts->vamos.peer;
+		/* fall-through */
 	case ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(0):
 	case ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(1):
 		lch_idx = cbits & 0x1;	/* TCH/H */
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index b0cffe5..b17bf01 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -95,18 +95,25 @@
 struct gsm_lchan *get_lchan_by_chan_nr(struct gsm_bts_trx *trx,
 				       unsigned int chan_nr)
 {
+	struct gsm_bts_trx_ts *ts;
 	unsigned int tn, ss;
 
 	tn = L1SAP_CHAN2TS(chan_nr);
-	OSMO_ASSERT(tn < ARRAY_SIZE(trx->ts));
+	ts = &trx->ts[tn];
+
+	if (L1SAP_IS_CHAN_VAMOS(chan_nr)) {
+		if (ts->vamos.peer == NULL)
+			return NULL;
+		ts = ts->vamos.peer;
+	}
 
 	if (L1SAP_IS_CHAN_CBCH(chan_nr))
 		ss = 2; /* CBCH is always on sub-slot 2 */
 	else
 		ss = l1sap_chan2ss(chan_nr);
-	OSMO_ASSERT(ss < ARRAY_SIZE(trx->ts[tn].lchan));
+	OSMO_ASSERT(ss < ARRAY_SIZE(ts->lchan));
 
-	return &trx->ts[tn].lchan[ss];
+	return &ts->lchan[ss];
 }
 
 static struct gsm_lchan *
@@ -1986,18 +1993,22 @@
 
 	/* Init DTX DL FSM if necessary */
 	if (trx->bts->dtxd && lchan->type != GSM_LCHAN_SDCCH) {
-		char name[32];
-		snprintf(name, sizeof(name), "bts%u-trx%u-ts%u-ss%u",
-			 trx->bts->nr, trx->nr, lchan->ts->nr, lchan->nr);
 		lchan->tch.dtx.dl_amr_fsm = osmo_fsm_inst_alloc(&dtx_dl_amr_fsm,
 								tall_bts_ctx,
 								lchan,
 								LOGL_DEBUG,
-								name);
+								NULL);
 		if (!lchan->tch.dtx.dl_amr_fsm) {
 			l1sap_chan_act_dact_modify(trx, chan_nr, PRIM_INFO_DEACTIVATE, 0);
 			return -RSL_ERR_EQUIPMENT_FAIL;
 		}
+
+		rc = osmo_fsm_inst_update_id_f(lchan->tch.dtx.dl_amr_fsm,
+					       "bts%u-trx%u-ts%u-ss%u%s",
+					       trx->bts->nr, trx->nr,
+					       lchan->ts->nr, lchan->nr,
+					       lchan->ts->vamos.is_shadow ? "-shadow" : "");
+		OSMO_ASSERT(rc == 0);
 	}
 	return 0;
 }
diff --git a/src/common/oml.c b/src/common/oml.c
index aba8847..0e7fbd5 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -837,9 +837,17 @@
 		ts->lchan[CCCH_LCHAN].type = GSM_LCHAN_CBCH;
 		break;
 	case GSM_PCHAN_TCH_F:
+		if (ts->vamos.peer != NULL) { /* VAMOS: enable shadow lchans */
+			lchans_type_set(ts->vamos.peer, GSM_LCHAN_TCH_F, 1);
+			ts->vamos.peer->pchan = GSM_PCHAN_TCH_F;
+		}
 		lchans_type_set(ts, GSM_LCHAN_TCH_F, 1);
 		break;
 	case GSM_PCHAN_TCH_H:
+		if (ts->vamos.peer != NULL) { /* VAMOS: enable shadow lchans */
+			lchans_type_set(ts->vamos.peer, GSM_LCHAN_TCH_H, 2);
+			ts->vamos.peer->pchan = GSM_PCHAN_TCH_H;
+		}
 		lchans_type_set(ts, GSM_LCHAN_TCH_H, 2);
 		break;
 	case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
@@ -849,6 +857,10 @@
 			ts->lchan[2].type = GSM_LCHAN_CBCH;
 		break;
 	case GSM_PCHAN_PDCH:
+		if (ts->vamos.peer != NULL) { /* VAMOS: disable shadow lchans */
+			lchans_type_set(ts->vamos.peer, GSM_LCHAN_NONE, 1);
+			ts->vamos.peer->pchan = GSM_PCHAN_NONE;
+		}
 		lchans_type_set(ts, GSM_LCHAN_PDTCH, 1);
 		break;
 	default:
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 6472e89..eb0aecd 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -744,6 +744,10 @@
 	struct osmo_phsap_prim *l1sap;
 	uint8_t chan_nr = trx_chan_desc[chan].chan_nr | l1ts->ts->nr;
 
+	/* VAMOS: use Osmocom specific channel number */
+	if (l1ts->ts->vamos.is_shadow)
+		chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* compose primitive */
 	msg = l1sap_msgb_alloc(l2_len);
 	l1sap = msgb_l1sap_prim(msg);
@@ -780,6 +784,10 @@
 	uint8_t chan_nr = trx_chan_desc[chan].chan_nr | l1ts->ts->nr;
 	struct gsm_lchan *lchan = &l1ts->ts->lchan[l1sap_chan2ss(chan_nr)];
 
+	/* VAMOS: use Osmocom specific channel number */
+	if (l1ts->ts->vamos.is_shadow)
+		chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* compose primitive */
 	msg = l1sap_msgb_alloc(tch_len);
 	l1sap = msgb_l1sap_prim(msg);
@@ -831,6 +839,10 @@
 		return 0;
 	}
 
+	/* VAMOS: convert Osmocom specific channel number to a generic one */
+	if (trx->ts[tn].vamos.is_shadow)
+		l1sap->u.data.chan_nr &= ~RSL_CHAN_OSMO_VAMOS_MASK;
+
 	msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg);
 
 	return 0;
@@ -853,6 +865,10 @@
 		return 0;
 	}
 
+	/* VAMOS: convert Osmocom specific channel number to a generic one */
+	if (trx->ts[tn].vamos.is_shadow)
+		l1sap->u.tch.chan_nr &= ~RSL_CHAN_OSMO_VAMOS_MASK;
+
 	msgb_enqueue(&l1ts->dl_prims, l1sap->oph.msg);
 
 	return 0;
@@ -874,6 +890,11 @@
 	chan_nr = trx_chan_desc[br->chan].chan_nr | br->tn;
 	link_id = trx_chan_desc[br->chan].link_id;
 
+
+	/* VAMOS: use Osmocom specific channel number */
+	if (l1ts->ts->vamos.is_shadow)
+		chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* For handover detection, there are cases where the SACCH should remain inactive until the first RACH
 	 * indicating the TA is received. */
 	if (L1SAP_IS_LINK_SACCH(link_id)
@@ -909,6 +930,11 @@
 	chan_nr = trx_chan_desc[br->chan].chan_nr | br->tn;
 	link_id = trx_chan_desc[br->chan].link_id;
 
+
+	/* VAMOS: use Osmocom specific channel number */
+	if (l1ts->ts->vamos.is_shadow)
+		chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK;
+
 	LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "TCH RTS.ind: chan_nr=0x%02x\n", chan_nr);
 
 	/* only send, if FACCH is selected */
@@ -1018,6 +1044,11 @@
 	bool found = false;
 	int i;
 
+	/* VAMOS: convert Osmocom specific channel number to a generic one,
+	 * otherwise we won't match anything in trx_chan_desc[]. */
+	if (lchan->ts->vamos.is_shadow)
+		chan_nr &= ~RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* look for all matching chan_nr/link_id */
 	for (i = 0; i < _TRX_CHAN_MAX; i++) {
 		struct l1sched_chan_state *chan_state = &l1ts->chan_state[i];
@@ -1081,6 +1112,11 @@
 	if (ts->pchan == GSM_PCHAN_PDCH)
 		return 0;
 
+	/* VAMOS: convert Osmocom specific channel number to a generic one,
+	 * otherwise we won't match anything in trx_chan_desc[]. */
+	if (ts->vamos.is_shadow)
+		chan_nr &= ~RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* look for all matching chan_nr/link_id */
 	for (i = 0; i < _TRX_CHAN_MAX; i++) {
 		if (trx_chan_desc[i].chan_nr == (chan_nr & 0xf8)
@@ -1133,6 +1169,11 @@
 	if (lchan->ts->pchan == GSM_PCHAN_PDCH)
 		return 0;
 
+	/* VAMOS: convert Osmocom specific channel number to a generic one,
+	 * otherwise we won't match anything in trx_chan_desc[]. */
+	if (lchan->ts->vamos.is_shadow)
+		chan_nr &= ~RSL_CHAN_OSMO_VAMOS_MASK;
+
 	/* no algorithm given means a5/0 */
 	if (algo <= 0)
 		algo = 0;
diff --git a/src/common/vty.c b/src/common/vty.c
index ccc63e6..8a1bafc 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -1642,8 +1642,9 @@
 {
 	struct in_addr ia;
 
-	vty_out(vty, "BTS %u, TRX %u, Timeslot %u, Lchan %u: Type %s%s",
+	vty_out(vty, "BTS %u, TRX %u, Timeslot %u (%s), Lchan %u: Type %s%s",
 		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
+		lchan->ts->vamos.is_shadow ? "shadow" : "primary",
 		lchan->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE);
 	/* show dyn TS details, if applicable */
 	switch (lchan->ts->pchan) {
@@ -1718,8 +1719,9 @@
 {
 	const struct gsm_meas_rep_unidir *mru = &lchan->meas.ul_res;
 
-	vty_out(vty, "BTS %u, TRX %u, Timeslot %u %s",
+	vty_out(vty, "BTS %u, TRX %u, Timeslot %u (%s) %s",
 		lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
+		lchan->ts->vamos.is_shadow ? "shadow" : "primary",
 		gsm_pchan_name(lchan->ts->pchan));
 	vty_out_dyn_ts_status(vty, lchan->ts);
 	vty_out(vty, ", Lchan %u, Type %s, State %s - "
@@ -1760,6 +1762,8 @@
 	for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
 		const struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
 		dump_lchan_trx_ts(ts, vty, dump_cb);
+		if (ts->vamos.peer != NULL) /* VAMOS: shadow timeslot */
+			dump_lchan_trx_ts(ts->vamos.peer, vty, dump_cb);
 	}
 
 	return CMD_SUCCESS;
@@ -1870,7 +1874,8 @@
 	int bts_nr = atoi(argv[idx+0]);
 	int trx_nr = atoi(argv[idx+1]);
 	int ts_nr = atoi(argv[idx+2]);
-	int lchan_nr = atoi(argv[idx+3]);
+	bool shadow = argv[idx+3][0] == 's';
+	int lchan_nr = atoi(argv[idx+4]);
 	struct gsm_bts *bts;
 	struct gsm_bts_trx *trx;
 	struct gsm_bts_trx_ts *ts;
@@ -1886,6 +1891,11 @@
 	if (ts_nr >= ARRAY_SIZE(trx->ts))
 		return NULL;
 	ts = &trx->ts[ts_nr];
+	if (shadow) { /* VAMOS shadow */
+		if (ts->vamos.peer == NULL)
+			return NULL;
+		ts = ts->vamos.peer;
+	}
 
 	if (lchan_nr >= ARRAY_SIZE(ts->lchan))
 		return NULL;
@@ -1894,7 +1904,7 @@
 }
 
 #define BTS_T_T_L_CMD \
-	"bts <0-0> trx <0-255> ts <0-7> lchan <0-7>"
+	"bts <0-0> trx <0-255> ts <0-7> (lchan|shadow-lchan) <0-7>"
 #define BTS_T_T_L_STR			\
 	"BTS related commands\n"	\
 	"BTS number\n"			\
@@ -1902,7 +1912,8 @@
 	"TRX number\n"			\
 	"timeslot related commands\n"	\
 	"timeslot number\n"		\
-	"logical channel commands\n"	\
+	"Primary logical channel commands\n"	\
+	"Shadow logical channel commands\n"	\
 	"logical channel number\n"
 
 DEFUN(cfg_bts_gsmtap_remote_host,

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/24153
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I48b44b4df9ffb1cca105aebbd868c29b21f3b1d6
Gerrit-Change-Number: 24153
Gerrit-PatchSet: 13
Gerrit-Owner: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210606/3e9aa9bd/attachment.htm>


More information about the gerrit-log mailing list