aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-virtual/scheduler_virtbts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-virtual/scheduler_virtbts.c')
-rw-r--r--src/osmo-bts-virtual/scheduler_virtbts.c318
1 files changed, 189 insertions, 129 deletions
diff --git a/src/osmo-bts-virtual/scheduler_virtbts.c b/src/osmo-bts-virtual/scheduler_virtbts.c
index c23632c5..0531ef61 100644
--- a/src/osmo-bts-virtual/scheduler_virtbts.c
+++ b/src/osmo-bts-virtual/scheduler_virtbts.c
@@ -28,6 +28,8 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/gsm/rsl.h>
#include <osmocom/netif/rtp.h>
@@ -44,23 +46,48 @@
extern void *tall_bts_ctx;
-
-
+/**
+ * Send a message over the virtual um interface.
+ * This will at first wrap the msg with a gsmtap header and then write it to the declared multicast socket.
+ */
static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, struct msgb *msg)
+ enum trx_chan_type chan, struct msgb *msg)
{
const struct trx_chan_desc *chdesc = &trx_chan_desc[chan];
- uint8_t ss = 0; //FIXME(chdesc);
- uint8_t gsmtap_chan;
+ uint8_t chan_type, timeslot, subslot, signal_dbm, signal_snr;
+ rsl_dec_chan_nr(chdesc->chan_nr, &chan_type, &subslot, &timeslot);
+ if (chan_type == RSL_CHAN_PCH_AGCH) {
+ if (L1SAP_FN2CCCHBLOCK(fn) >= 1) {
+ chan_type = GSMTAP_CHANNEL_PCH;
+ } else {
+ chan_type = GSMTAP_CHANNEL_AGCH;
+ }
+ } else {
+ chan_type = chantype_rsl2gsmtap(chan_type, chdesc->link_id); // the logical channel type
+ }
+ //uint8_t timeslot = tn; // indicates the physical channel
+ //uint8_t subslot = 0; // indicates the logical channel subslot on the physical channel FIXME: calculate
+ signal_dbm = 63; // the signal strength is not needed in virt phy
+ signal_snr = 40; // the signal to noice ratio is not needed in virt phy
+ uint8_t *data = msgb_l2(msg); // data bits to transmit (whole message without l1 header)
+ uint8_t data_len = msgb_l2len(msg);
struct msgb *outmsg;
- gsmtap_chan = chantype_rsl2gsmtap(chdesc->chan_nr, chdesc->link_id);
- outmsg = gsmtap_makemsg(l1t->trx->arfcn, tn, gsmtap_chan, ss, fn,
- 0, 0, msgb_l2(msg), msgb_l2len(msg));
+ // TODO: encrypt and encode message data
+
+ outmsg = gsmtap_makemsg(l1t->trx->arfcn, timeslot, chan_type, subslot,
+ fn, signal_dbm, signal_snr, data, data_len);
if (outmsg) {
struct phy_instance *pinst = trx_phy_instance(l1t->trx);
struct virt_um_inst *virt_um = pinst->phy_link->u.virt.virt_um;
- virt_um_write_msg(virt_um, outmsg);
+ if (virt_um_write_msg(virt_um, outmsg) == -1) {
+ struct gsmtap_hdr *gh = (struct gsmtap_hdr *)msgb_data(
+ outmsg);
+ LOGP(DL1C, LOGL_ERROR,
+ "Message could not be written to virtual UM! arfcn = %u gsmtap_chan=%u fn=%u ts=%u\n",
+ gh->arfcn, gh->type, gh->frame_number,
+ gh->timeslot);
+ }
}
/* free message */
@@ -73,62 +100,67 @@ static void tx_to_virt_um(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */
ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
return NULL;
}
ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
return NULL;
}
ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
return NULL;
}
ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
struct msgb *msg;
+ if (fn == 57) {
+ DEBUGP(DL1P, "lol");
+ }
+
if (bid > 0)
return NULL;
/* get mac block from queue */
+ // what queue is that and who does fill it?
msg = _sched_dequeue_prim(l1t, tn, fn, chan);
if (msg)
goto got_msg;
LOGP(DL1P, LOGL_INFO, "%s has not been served !! No prim for "
- "trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
+ "trx=%u ts=%u at fn=%u to transmit.\n",
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
-no_msg:
- return NULL;
+ no_msg: return NULL;
-got_msg:
+ got_msg:
/* check validity of message */
if (msgb_l2len(msg) != GSM_MACBLOCK_LEN) {
LOGP(DL1P, LOGL_FATAL, "Prim not 23 bytes, please FIX! "
- "(len=%d)\n", msgb_l2len(msg));
+ "(len=%d)\n", msgb_l2len(msg));
/* free message */
msgb_free(msg);
goto no_msg;
}
+ // transmit the msg received on dl from bsc to layer1 (virt um)
tx_to_virt_um(l1t, tn, fn, chan, msg);
return NULL;
}
ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
@@ -144,21 +176,20 @@ ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
goto got_msg;
LOGP(DL1P, LOGL_INFO, "%s has not been served !! No prim for "
- "trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
+ "trx=%u ts=%u at fn=%u to transmit.\n",
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
-no_msg:
- return NULL;
+ no_msg: return NULL;
-got_msg:
- tx_to_virt_um(l1t, tn, fn, chan, msg);
+ got_msg: tx_to_virt_um(l1t, tn, fn, chan, msg);
return NULL;
}
static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, struct msgb **_msg_tch,
- struct msgb **_msg_facch, int codec_mode_request)
+ enum trx_chan_type chan, uint8_t bid,
+ struct msgb **_msg_tch, struct msgb **_msg_facch,
+ int codec_mode_request)
{
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
struct msgb *msg1, *msg2, *msg_tch = NULL, *msg_facch = NULL;
@@ -169,16 +200,16 @@ static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
#if 0
/* handle loss detection of received TCH frames */
if (rsl_cmode == RSL_CMOD_SPD_SPEECH
- && ++(chan_state->lost) > 5) {
+ && ++(chan_state->lost) > 5) {
uint8_t tch_data[GSM_FR_BYTES];
int len;
LOGP(DL1P, LOGL_NOTICE, "Missing TCH bursts detected, sending "
- "BFI for %s\n", trx_chan_desc[chan].name);
+ "BFI for %s\n", trx_chan_desc[chan].name);
/* indicate bad frame */
switch (tch_mode) {
- case GSM48_CMODE_SPEECH_V1: /* FR / HR */
+ case GSM48_CMODE_SPEECH_V1: /* FR / HR */
if (chan != TRXC_TCHF) { /* HR */
tch_data[0] = 0x70; /* F = 0, FT = 111 */
memset(tch_data + 1, 0, 14);
@@ -188,29 +219,29 @@ static void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
memset(tch_data, 0, GSM_FR_BYTES);
len = GSM_FR_BYTES;
break;
- case GSM48_CMODE_SPEECH_EFR: /* EFR */
+ case GSM48_CMODE_SPEECH_EFR: /* EFR */
if (chan != TRXC_TCHF)
- goto inval_mode1;
+ goto inval_mode1;
memset(tch_data, 0, GSM_EFR_BYTES);
len = GSM_EFR_BYTES;
break;
- case GSM48_CMODE_SPEECH_AMR: /* AMR */
+ case GSM48_CMODE_SPEECH_AMR: /* AMR */
len = amr_compose_payload(tch_data,
- chan_state->codec[chan_state->dl_cmr],
- chan_state->codec[chan_state->dl_ft], 1);
+ chan_state->codec[chan_state->dl_cmr],
+ chan_state->codec[chan_state->dl_ft], 1);
if (len < 2)
- break;
+ break;
memset(tch_data + 2, 0, len - 2);
_sched_compose_tch_ind(l1t, tn, 0, chan, tch_data, len);
break;
- default:
-inval_mode1:
+ default:
+ inval_mode1:
LOGP(DL1P, LOGL_ERROR, "TCH mode invalid, please "
- "fix!\n");
+ "fix!\n");
len = 0;
}
if (len)
- _sched_compose_tch_ind(l1t, tn, 0, chan, tch_data, len);
+ _sched_compose_tch_ind(l1t, tn, 0, chan, tch_data, len);
}
#endif
@@ -225,7 +256,7 @@ inval_mode1:
l1sap = msgb_l1sap_prim(msg2);
if (l1sap->oph.primitive == PRIM_TCH) {
LOGP(DL1P, LOGL_FATAL, "TCH twice, "
- "please FIX! ");
+ "please FIX! ");
msgb_free(msg2);
} else
msg_facch = msg2;
@@ -236,7 +267,7 @@ inval_mode1:
l1sap = msgb_l1sap_prim(msg2);
if (l1sap->oph.primitive != PRIM_TCH) {
LOGP(DL1P, LOGL_FATAL, "FACCH twice, "
- "please FIX! ");
+ "please FIX! ");
msgb_free(msg2);
} else
msg_tch = msg2;
@@ -253,7 +284,7 @@ inval_mode1:
/* check validity of message */
if (msg_facch && msgb_l2len(msg_facch) != GSM_MACBLOCK_LEN) {
LOGP(DL1P, LOGL_FATAL, "Prim not 23 bytes, please FIX! "
- "(len=%d)\n", msgb_l2len(msg_facch));
+ "(len=%d)\n", msgb_l2len(msg_facch));
/* free message */
msgb_free(msg_facch);
msg_facch = NULL;
@@ -266,10 +297,12 @@ inval_mode1:
int cmr, ft, i;
if (rsl_cmode != RSL_CMOD_SPD_SPEECH) {
- LOGP(DL1P, LOGL_NOTICE, "%s Dropping speech frame, "
- "because we are not in speech mode trx=%u "
- "ts=%u at fn=%u.\n", trx_chan_desc[chan].name,
- l1t->trx->nr, tn, fn);
+ LOGP(DL1P, LOGL_NOTICE,
+ "%s Dropping speech frame, "
+ "because we are not in speech mode trx=%u "
+ "ts=%u at fn=%u.\n",
+ trx_chan_desc[chan].name, l1t->trx->nr,
+ tn, fn);
goto free_bad_msg;
}
@@ -278,24 +311,27 @@ inval_mode1:
if (chan != TRXC_TCHF) { /* HR */
len = 15;
if (msgb_l2len(msg_tch) >= 1
- && (msg_tch->l2h[0] & 0xf0) != 0x00) {
- LOGP(DL1P, LOGL_NOTICE, "%s "
- "Transmitting 'bad "
- "HR frame' trx=%u ts=%u at "
- "fn=%u.\n",
- trx_chan_desc[chan].name,
- l1t->trx->nr, tn, fn);
+ && (msg_tch->l2h[0] & 0xf0)
+ != 0x00) {
+ LOGP(DL1P, LOGL_NOTICE,
+ "%s "
+ "Transmitting 'bad "
+ "HR frame' trx=%u ts=%u at "
+ "fn=%u.\n",
+ trx_chan_desc[chan].name,
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
}
len = GSM_FR_BYTES;
if (msgb_l2len(msg_tch) >= 1
- && (msg_tch->l2h[0] >> 4) != 0xd) {
- LOGP(DL1P, LOGL_NOTICE, "%s Transmitting 'bad "
- "FR frame' trx=%u ts=%u at fn=%u.\n",
- trx_chan_desc[chan].name,
- l1t->trx->nr, tn, fn);
+ && (msg_tch->l2h[0] >> 4) != 0xd) {
+ LOGP(DL1P, LOGL_NOTICE,
+ "%s Transmitting 'bad "
+ "FR frame' trx=%u ts=%u at fn=%u.\n",
+ trx_chan_desc[chan].name,
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
@@ -304,26 +340,27 @@ inval_mode1:
goto inval_mode2;
len = GSM_EFR_BYTES;
if (msgb_l2len(msg_tch) >= 1
- && (msg_tch->l2h[0] >> 4) != 0xc) {
- LOGP(DL1P, LOGL_NOTICE, "%s Transmitting 'bad "
- "EFR frame' trx=%u ts=%u at fn=%u.\n",
- trx_chan_desc[chan].name,
- l1t->trx->nr, tn, fn);
+ && (msg_tch->l2h[0] >> 4) != 0xc) {
+ LOGP(DL1P, LOGL_NOTICE,
+ "%s Transmitting 'bad "
+ "EFR frame' trx=%u ts=%u at fn=%u.\n",
+ trx_chan_desc[chan].name,
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
break;
case GSM48_CMODE_SPEECH_AMR: /* AMR */
#if 0
len = amr_decompose_payload(msg_tch->l2h,
- msgb_l2len(msg_tch), &cmr_codec, &ft_codec,
- &bfi);
+ msgb_l2len(msg_tch), &cmr_codec, &ft_codec,
+ &bfi);
cmr = -1;
ft = -1;
for (i = 0; i < chan_state->codecs; i++) {
if (chan_state->codec[i] == cmr_codec)
- cmr = i;
+ cmr = i;
if (chan_state->codec[i] == ft_codec)
- ft = i;
+ ft = i;
}
if (cmr >= 0) { /* new request */
chan_state->dl_cmr = cmr;
@@ -335,46 +372,47 @@ inval_mode1:
}
if (ft < 0) {
LOGP(DL1P, LOGL_ERROR, "%s Codec (FT = %d) "
- " of RTP frame not in list. "
- "trx=%u ts=%u\n",
- trx_chan_desc[chan].name, ft_codec,
- l1t->trx->nr, tn);
+ " of RTP frame not in list. "
+ "trx=%u ts=%u\n",
+ trx_chan_desc[chan].name, ft_codec,
+ l1t->trx->nr, tn);
goto free_bad_msg;
}
if (codec_mode_request && chan_state->dl_ft != ft) {
LOGP(DL1P, LOGL_NOTICE, "%s Codec (FT = %d) "
- " of RTP cannot be changed now, but in "
- "next frame. trx=%u ts=%u\n",
- trx_chan_desc[chan].name, ft_codec,
- l1t->trx->nr, tn);
+ " of RTP cannot be changed now, but in "
+ "next frame. trx=%u ts=%u\n",
+ trx_chan_desc[chan].name, ft_codec,
+ l1t->trx->nr, tn);
goto free_bad_msg;
}
chan_state->dl_ft = ft;
if (bfi) {
LOGP(DL1P, LOGL_NOTICE, "%s Transmitting 'bad "
- "AMR frame' trx=%u ts=%u at fn=%u.\n",
- trx_chan_desc[chan].name,
- l1t->trx->nr, tn, fn);
+ "AMR frame' trx=%u ts=%u at fn=%u.\n",
+ trx_chan_desc[chan].name,
+ l1t->trx->nr, tn, fn);
goto free_bad_msg;
}
#endif
break;
default:
-inval_mode2:
+ inval_mode2:
LOGP(DL1P, LOGL_ERROR, "TCH mode invalid, please "
- "fix!\n");
+ "fix!\n");
goto free_bad_msg;
}
if (len < 0) {
LOGP(DL1P, LOGL_ERROR, "Cannot send invalid AMR "
- "payload\n");
+ "payload\n");
goto free_bad_msg;
}
if (msgb_l2len(msg_tch) != len) {
- LOGP(DL1P, LOGL_ERROR, "Cannot send payload with "
- "invalid length! (expecing %d, received %d)\n",
- len, msgb_l2len(msg_tch));
-free_bad_msg:
+ LOGP(DL1P, LOGL_ERROR,
+ "Cannot send payload with "
+ "invalid length! (expecing %d, received %d)\n",
+ len, msgb_l2len(msg_tch));
+ free_bad_msg:
/* free message */
msgb_free(msg_tch);
msg_tch = NULL;
@@ -382,13 +420,12 @@ free_bad_msg:
}
}
-send_frame:
- *_msg_tch = msg_tch;
+ send_frame: *_msg_tch = msg_tch;
*_msg_facch = msg_facch;
}
ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
struct msgb *msg_tch = NULL, *msg_facch = NULL;
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
@@ -400,13 +437,13 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
return NULL;
tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
- (((fn + 4) % 26) >> 2) & 1);
+ (((fn + 4) % 26) >> 2) & 1);
/* no message at all */
if (!msg_tch && !msg_facch) {
LOGP(DL1P, LOGL_INFO, "%s has not been served !! No prim for "
- "trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
+ "trx=%u ts=%u at fn=%u to transmit.\n",
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
goto send_burst;
}
@@ -416,13 +453,13 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
} else
tx_to_virt_um(l1t, tn, fn, chan, msg_tch);
-send_burst:
+ send_burst:
return NULL;
}
ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid)
+ enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
{
struct msgb *msg_tch = NULL, *msg_facch = NULL;
struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
@@ -436,13 +473,13 @@ ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* get TCH and/or FACCH */
tx_tch_common(l1t, tn, fn, chan, bid, &msg_tch, &msg_facch,
- (((fn + 4) % 26) >> 2) & 1);
+ (((fn + 4) % 26) >> 2) & 1);
/* check for FACCH alignment */
if (msg_facch && ((((fn + 4) % 26) >> 2) & 1)) {
LOGP(DL1P, LOGL_ERROR, "%s Cannot transmit FACCH starting on "
- "even frames, please fix RTS!\n",
- trx_chan_desc[chan].name);
+ "even frames, please fix RTS!\n",
+ trx_chan_desc[chan].name);
msgb_free(msg_facch);
msg_facch = NULL;
}
@@ -450,8 +487,8 @@ ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* no message at all */
if (!msg_tch && !msg_facch && !chan_state->dl_ongoing_facch) {
LOGP(DL1P, LOGL_INFO, "%s has not been served !! No prim for "
- "trx=%u ts=%u at fn=%u to transmit.\n",
- trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
+ "trx=%u ts=%u at fn=%u to transmit.\n",
+ trx_chan_desc[chan].name, l1t->trx->nr, tn, fn);
goto send_burst;
}
@@ -461,11 +498,9 @@ ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
} else
tx_to_virt_um(l1t, tn, fn, chan, msg_tch);
-send_burst:
- return NULL;
+ send_burst: return NULL;
}
-
/***********************************************************************
* RX on uplink (indication to upper layer)
***********************************************************************/
@@ -475,42 +510,43 @@ send_burst:
* towards receiving bursts */
int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
- float toa)
+ enum trx_chan_type chan, uint8_t bid, sbit_t *bits,
+ uint16_t nbits, int8_t rssi, float toa)
{
return 0;
}
/*! \brief a single burst was received by the PHY, process it */
int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
- float toa)
+ enum trx_chan_type chan, uint8_t bid, sbit_t *bits,
+ uint16_t nbits, int8_t rssi, float toa)
{
return 0;
}
int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
- float toa)
+ enum trx_chan_type chan, uint8_t bid, sbit_t *bits,
+ uint16_t nbits, int8_t rssi, float toa)
{
return 0;
}
int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
- float toa)
+ enum trx_chan_type chan, uint8_t bid, sbit_t *bits,
+ uint16_t nbits, int8_t rssi, float toa)
{
return 0;
}
int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
- enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
- float toa)
+ enum trx_chan_type chan, uint8_t bid, sbit_t *bits,
+ uint16_t nbits, int8_t rssi, float toa)
{
return 0;
}
-void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate)
+void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss,
+ int activate)
{
}
@@ -524,22 +560,36 @@ void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int ac
static int vbts_sched_fn(struct gsm_bts *bts, uint32_t fn)
{
struct gsm_bts_trx *trx;
+ uint16_t nbits;
/* send time indication */
+ // update model with new frame number, lot of stuff happening, mesurements of timeslots
+ // saving gsm time in bts model, and more
l1if_mph_time_ind(bts, fn);
/* advance the frame number? */
-
- llist_for_each_entry(trx, &bts->trx_list, list) {
+ // is this the time advance functionality that depends of the distance to the ms???
+ llist_for_each_entry(trx, &bts->trx_list, list)
+ {
struct phy_instance *pinst = trx_phy_instance(trx);
struct l1sched_trx *l1t = &pinst->u.virt.sched;
int tn;
-
+ const ubit_t *bits;
+ // do for each of the 8 timeslots
for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
- /* Generate RTS.ind to higher layers */
- _sched_rts(l1t, tn, (fn + RTS_ADVANCE) % GSM_HYPERFRAME);
+ /* Generate RTS indication to higher layers */
+ // ST: This will basically do 2 things (check l1_if:bts_model_l1sap_down):
+ // 1) Get pending messages from layer 2 (from the lapdm queue)
+ // 2) Process the messages
+ // --> Handle and process non-transparent RSL-Messages (activate channel, )
+ // --> Forward transparent RSL-DATA-Messages to the ms by appending them to the l1-dl-queue
+ _sched_rts(l1t, tn,
+ (fn + RTS_ADVANCE) % GSM_HYPERFRAME);
/* schedule transmit backend functions */
- _sched_dl_burst(l1t, tn, fn);
+ // ST: Process data in the l1-dlqueue and forward it to ms
+ // the returned bits are not used here, the routines called will directly forward their bits to the virt um
+ bits = _sched_dl_burst(l1t, tn, fn, &nbits);
+
}
}
@@ -556,25 +606,34 @@ static void vbts_fn_timer_cb(void *data)
gettimeofday(&tv_now, NULL);
- elapsed_us = (tv_now.tv_sec - tv_clock->tv_sec) * 1000000 +
- (tv_now.tv_usec - tv_clock->tv_usec);
+ // check how much time elapsed till the last timer callback call
+ // this value should be about 4.615 ms (a bit greater) as this is the scheduling interval
+ elapsed_us = (tv_now.tv_sec - tv_clock->tv_sec) * 1000000
+ + (tv_now.tv_usec - tv_clock->tv_usec);
- if (elapsed_us > 2*FRAME_DURATION_uS)
- LOGP(DL1P, LOGL_NOTICE, "vbts_fn_timer_cb after %d us\n", elapsed_us);
+ // not so good somehow a lot of time passed between two timer callbacks
+ if (elapsed_us > 2 * FRAME_DURATION_uS)
+ LOGP(DL1P, LOGL_NOTICE, "vbts_fn_timer_cb after %d us\n",
+ elapsed_us);
+ // schedule the current frame/s (fn = frame number)
+ // this loop will be called at least once, but can also be executed
+ // multiple times if more than one frame duration (4615us) passed till the last callback
while (elapsed_us > FRAME_DURATION_uS / 2) {
- const struct timeval tv_frame = {
- .tv_sec = 0,
- .tv_usec = FRAME_DURATION_uS,
- };
+ const struct timeval tv_frame = {.tv_sec = 0, .tv_usec =
+ FRAME_DURATION_uS, };
timeradd(tv_clock, &tv_frame, tv_clock);
+ // increment the frame number in the bts model instance
btsb->vbts.last_fn = (btsb->vbts.last_fn + 1) % GSM_HYPERFRAME;
vbts_sched_fn(bts, btsb->vbts.last_fn);
elapsed_us -= FRAME_DURATION_uS;
}
/* re-schedule the timer */
- osmo_timer_schedule(&btsb->vbts.fn_timer, 0, FRAME_DURATION_uS - elapsed_us);
+ // timer is set to frame duration - elapsed time to guarantee that this cb method will be
+ // periodically executed every 4.615ms
+ osmo_timer_schedule(&btsb->vbts.fn_timer, 0,
+ FRAME_DURATION_uS - elapsed_us);
}
int vbts_sched_start(struct gsm_bts *bts)
@@ -588,6 +647,7 @@ int vbts_sched_start(struct gsm_bts *bts)
btsb->vbts.fn_timer.data = bts;
gettimeofday(&btsb->vbts.tv_clock, NULL);
+ // trigger the first timer after 4615us (a frame duration)
osmo_timer_schedule(&btsb->vbts.fn_timer, 0, FRAME_DURATION_uS);
return 0;