VIRT-PHY: Calculate correct scheduler fn for data- and tch-msgs on ul.

Proper calculation of the scheduled frame number and appending the jobs
with that fn to the scheduler. Thus uplink msgs are scheduled at the
(approx.) correct fn and with this fn set in the gsmtap hdr.

Change-Id: I0f44d0b5b9208755e671c619d1f851a043aefb54
This commit is contained in:
Sebastian Stumpf 2017-02-27 18:16:44 +01:00 committed by Harald Welte
parent 241fe9c3e2
commit 30cc674df8
10 changed files with 385 additions and 36 deletions

View File

@ -1,3 +1,4 @@
config.h
config.h.in
src/virtphy
src/virtphy
.dirstamp

View File

@ -10,7 +10,7 @@ void gsmtapl1_init(struct l1_model_ms *model);
void gsmtapl1_rx_from_virt_um_inst_cb(struct virt_um_inst *vui,
struct msgb *msg);
void gsmtapl1_rx_from_virt_um(struct msgb *msg);
void gsmtapl1_tx_to_virt_um_inst(struct virt_um_inst *vui, struct msgb *msg);
void gsmtapl1_tx_to_virt_um(struct msgb *msg);
void gsmtapl1_tx_to_virt_um_inst(uint32_t fn, struct virt_um_inst *vui, struct msgb *msg);
void gsmtapl1_tx_to_virt_um(uint32_t fn, struct msgb *msg);
void chantype_gsmtap2rsl(uint8_t gsmtap_chantype, uint8_t *rsl_chantype,
uint8_t *link_id);

View File

@ -60,3 +60,7 @@ void l1ctl_tx_fbsb_conf(uint8_t res, uint16_t arfcn);
void l1ctl_tx_ccch_mode_conf(uint8_t ccch_mode);
void l1ctl_tx_tch_mode_conf(uint8_t tch_mode, uint8_t audio_mode);
void l1ctl_tx_msg(uint8_t msg_type);
/* scheduler functions */
uint32_t sched_fn_ul(struct gsm_time cur_time, uint8_t chan_nr,
uint8_t link_id);

View File

@ -5,7 +5,7 @@
#include <osmocom/gsm/gsm_utils.h>
#include <virtphy/virt_l1_sched.h>
typedef void virt_l1_sched_cb(struct msgb * msg);
typedef void virt_l1_sched_cb(uint32_t fn, struct msgb * msg);
/* bucket containing items to be executed for a specific mframe number */
struct virt_l1_sched_mframe_item {

View File

@ -90,13 +90,12 @@ void gsmtapl1_init(struct l1_model_ms *model)
/**
* Replace l11 header of given msgb by a gsmtap header and send it over the virt um.
*/
void gsmtapl1_tx_to_virt_um_inst(struct virt_um_inst *vui, struct msgb *msg)
void gsmtapl1_tx_to_virt_um_inst(uint32_t fn, struct virt_um_inst *vui, struct msgb *msg)
{
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
struct gsmtap_hdr *gh;
struct msgb *outmsg; // msg to send with gsmtap header prepended
uint32_t fn = gsm_gsmtime2fn(&l1_model_ms->state->downlink_time);
uint16_t arfcn = l1_model_ms->state->serving_cell.arfcn; // arfcn of the cell we currently camp on
uint8_t signal_dbm = 63; // signal strength, 63 is best
uint8_t snr = 63; // signal noise ratio, 63 is best
@ -140,9 +139,9 @@ void gsmtapl1_tx_to_virt_um_inst(struct virt_um_inst *vui, struct msgb *msg)
/**
* @see void gsmtapl1_tx_to_virt_um(struct virt_um_inst *vui, uint32_t fn, struct msgb *msg).
*/
void gsmtapl1_tx_to_virt_um(struct msgb *msg)
void gsmtapl1_tx_to_virt_um(uint32_t fn, struct msgb *msg)
{
gsmtapl1_tx_to_virt_um_inst(l1_model_ms->vui, msg);
gsmtapl1_tx_to_virt_um_inst(fn, l1_model_ms->vui, msg);
}
/**

View File

@ -666,3 +666,351 @@ void l1ctl_tx_tch_mode_conf(uint8_t tch_mode, uint8_t audio_mode)
l1ctl_sap_tx_to_l23(msg);
}
/**
* @brief Get the scheduled fn for a msg depending on its chan_nr and link_id.
*/
uint32_t sched_fn_ul(struct gsm_time cur_time, uint8_t chan_nr,
uint8_t link_id)
{
uint8_t chan_type, chan_ss, chan_ts;
rsl_dec_chan_nr(chan_nr, &chan_type, &chan_ss, &chan_ts);
uint32_t sched_fn = cur_time.fn;
uint16_t mod_102 = cur_time.fn % 2 * 51;
switch (chan_type) {
case RSL_CHAN_Bm_ACCHs:
switch (link_id) {
case LID_DEDIC:
// dl=[0...11,13...24] ul=[0...11,13...24]
// skip idle frames and frames reserved for TCH_ACCH
if(cur_time.t2 == 12 || cur_time.t2 == 25) {
sched_fn++;
}
break;
// dl=42, ul=42+15
case LID_SACCH:
if((chan_ts & 1)) {
// Odd traffic channel timeslot -> dl=[25] ul=[25]
// TCH_ACCH always at the end of tch multiframe (mod 26)
sched_fn -= cur_time.t2;
sched_fn += 25;
}
else {
// Even traffic channel timeslot -> dl=[12] ul=[12]
if(cur_time.t2 <= 12) {
sched_fn -= cur_time.t2;
sched_fn += 12;
} else {
sched_fn -= cur_time.t2;
sched_fn += 26 + 12;
}
}
break;
}
break;
case RSL_CHAN_Lm_ACCHs:
break; /* TCH/H not supported */
case RSL_CHAN_SDCCH4_ACCH:
switch (chan_ss) {
case 0:
switch (link_id) {
// dl=22, ul=22+15
case LID_DEDIC:
if(cur_time.t3 <= 22 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 22 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 22 + 15;
}
break;
// dl=42, ul=42+15
case LID_SACCH:
if(mod_102 <= 42 + 15) {
sched_fn -= mod_102;
sched_fn += 42 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 42 + 15;
}
break;
}
break;
case 1:
switch (link_id) {
// dl=26, ul=26+15
case LID_DEDIC:
if(cur_time.t3 <= 26 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 26 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 26 + 15;
}
break;
// dl=46, ul=46+15
case LID_SACCH:
if(mod_102 <= 46 + 15) {
sched_fn -= mod_102;
sched_fn += 46 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 46 + 15;
}
break;
}
break;
case 2:
switch (link_id) {
// dl=32, ul=32+15
case LID_DEDIC:
if(cur_time.t3 <= 32 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 32 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 32 + 15;
}
break;
// dl=51+42, ul=51+42+15
case LID_SACCH:
if(mod_102 <= 51 + 42 + 15) {
sched_fn -= mod_102;
sched_fn += 51 + 42 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 51 + 42 + 15;
}
break;
}
break;
case 3:
switch (link_id) {
// dl=36, ul=36+15
case LID_DEDIC:
if(cur_time.t3 <= 36 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 36 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 36 + 15;
}
break;
// dl=51+46, ul=51+46+15
case LID_SACCH:
if(mod_102 <= 51 + 46 + 15) {
sched_fn -= mod_102;
sched_fn += 51 + 46 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 51 + 46 + 15;
}
break;
}
break;
}
break;
case RSL_CHAN_SDCCH8_ACCH:
switch (chan_ss) {
case 0:
switch (link_id) {
// dl=0, ul=0+15
case LID_DEDIC:
if(cur_time.t3 <= 0 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 0 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 0 + 15;
}
break;
// dl=32, ul=32+15
case LID_SACCH:
if(mod_102 <= 32 + 15) {
sched_fn -= mod_102;
sched_fn += 32 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 32 + 15;
}
break;
}
break;
case 1:
switch (link_id) {
// dl=4, ul=4+15
case LID_DEDIC:
if(cur_time.t3 <= 4 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 4 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 4 + 15;
}
break;
// dl=36, ul=36+15
case LID_SACCH:
if(mod_102 <= 36 + 15) {
sched_fn -= mod_102;
sched_fn += 36 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 36 + 15;
}
break;
}
break;
case 2:
switch (link_id) {
// dl=8, ul=8+15
case LID_DEDIC:
if(cur_time.t3 <= 8 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 8 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 8 + 15;
}
break;
// dl=40, ul=40+15
case LID_SACCH:
if(mod_102 <= 40 + 15) {
sched_fn -= mod_102;
sched_fn += 40 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 40 + 15;
}
break;
}
break;
case 3:
switch (link_id) {
// dl=12, ul=12+15
case LID_DEDIC:
if(cur_time.t3 <= 12 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 12 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 12 + 15;
}
break;
// dl=44, ul=44+15
case LID_SACCH:
if(mod_102 <= 44 + 15) {
sched_fn -= mod_102;
sched_fn += 44 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 44 + 15;
}
break;
}
break;
case 4:
switch (link_id) {
// dl=16, ul=16+15
case LID_DEDIC:
if(cur_time.t3 <= 16 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 16 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 16 + 15;
}
break;
// dl=51+32, ul=51+32+15
case LID_SACCH:
if(mod_102 <= 51 + 32 + 15) {
sched_fn -= mod_102;
sched_fn += 51 + 32 + 15;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 51 + 32 + 15;
}
break;
}
break;
case 5:
switch (link_id) {
// dl=20, ul=36+15
case LID_DEDIC:
if(cur_time.t3 <= 20 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 20 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 20 + 15;
}
break;
// dl=51+36, ul=51+36+15 ==> 0
case LID_SACCH:
if(mod_102 <= 0) {
sched_fn -= mod_102;
sched_fn += 0;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 0;
}
break;
}
break;
case 6:
switch (link_id) {
// dl=24, ul=24+15
case LID_DEDIC:
if(cur_time.t3 <= 24 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 24 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 24 + 15;
}
break;
// dl=51+40, ul=51+40+15 ==> 4
case LID_SACCH:
if(mod_102 <= 4) {
sched_fn -= mod_102;
sched_fn += 4;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 4;
}
break;
}
break;
case 7:
switch (link_id) {
// dl=28, ul=28+15
case LID_DEDIC:
if(cur_time.t3 <= 28 + 15) {
sched_fn -= cur_time.t3;
sched_fn += 28 + 15;
} else {
sched_fn -= cur_time.t3;
sched_fn += 51 + 28 + 15;
}
break;
// dl=51+44, ul=51+44+15 ==> 8
case LID_SACCH:
if(mod_102 <= 8) {
sched_fn -= mod_102;
sched_fn += 8;
} else {
sched_fn -= mod_102;
sched_fn += 2 * 51 + 8;
}
break;
}
break;
}
break;
case RSL_CHAN_RACH:
break; /* Use virt_prim_rach.c for calculation of sched fn for rach */
default:
break; /* Use current fn as default */
}
return sched_fn;
}

View File

@ -80,7 +80,7 @@ void virt_l1_sched_execute(uint32_t fn)
{
// exec tdma sched item's handler callback
// TODO: we do not have a tdma scheduler currently and execute alle scheduled tdma items here at once
ti_next->handler_cb(ti_next->msg);
ti_next->handler_cb(mi_next->fn, ti_next->msg);
// remove handled tdma sched item
llist_del(&ti_next->tdma_item_entry);
}

View File

@ -1,4 +1,4 @@
/* Layer 1 normal data burst tx handling */
/* Layer 1 normal data burst uplink handling and scheduling */
/* (C) 2010 by Dieter Spaar <spaar@mirider.augusta.de>
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
@ -37,19 +37,19 @@
#include <l1ctl_proto.h>
static struct l1_model_ms *l1_model_ms = NULL;
static void virt_l1_sched_handler_cb(struct msgb * msg);
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg);
/**
* @brief Handler callback function for DATA request.
*
* @param [in] msg the msg to sent over virtual um.
*/
static void virt_l1_sched_handler_cb(struct msgb * msg)
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg)
{
gsmtapl1_tx_to_virt_um(msg);
gsmtapl1_tx_to_virt_um(fn, msg);
// send confirm to layer23
// FIXME: as we might send multiple burst, the base fn may be another one than the current
msg = l1ctl_create_l2_msg(L1CTL_DATA_CONF, l1_model_ms->state->current_time.fn, 0, 0);
msg = l1ctl_create_l2_msg(L1CTL_DATA_CONF,
fn, 0, 0);
l1ctl_sap_tx_to_l23(msg);
}
@ -62,28 +62,26 @@ static void virt_l1_sched_handler_cb(struct msgb * msg)
*
* Transmit message on a signalling channel. FACCH/SDCCH or SACCH depending on the headers set link id (TS 8.58 - 9.3.2).
*
* TODO: Check if a msg on FACCH is coming in here and needs special handling.
* TODO: Check if msg contains data of a burst or data of 4 bursts!
* TODO: Check if a msg on FACCH needs special handling.
*/
void l1ctl_rx_data_req(struct msgb *msg)
{
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
struct l1ctl_data_ind *data_ind = (struct l1ctl_data_ind *)ul->payload;
// TODO: calc the scheduled fn
uint32_t fn_sched = l1_model_ms->state->current_time.fn;
uint8_t rsl_chantype, subslot, timeslot;
uint32_t fn_sched = sched_fn_ul(l1_model_ms->state->current_time, ul->chan_nr, ul->link_id);
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
DEBUGP(DL1C,
"Received and handled from l23 - L1CTL_DATA_REQ (link_id=0x%02x, ul=%p, ul->payload=%p, data_ind=%p, data_ind->data=%p l3h=%p)\n",
ul->link_id, ul, ul->payload, data_ind, data_ind->data,
msg->l3h);
"Received and handled from l23 - L1CTL_DATA_REQ (link_id=0x%02x, ul=%p, ul->payload=%p, data_ind=%p, data_ind->data=%p l3h=%p)\n",
ul->link_id, ul, ul->payload, data_ind, data_ind->data,
msg->l3h);
msg->l2h = data_ind->data;
virt_l1_sched_schedule(msg, fn_sched, timeslot, &virt_l1_sched_handler_cb);
virt_l1_sched_schedule(msg, fn_sched, timeslot,
&virt_l1_sched_handler_cb);
}

View File

@ -37,7 +37,7 @@
#include <l1ctl_proto.h>
static struct l1_model_ms *l1_model_ms = NULL;
static void virt_l1_sched_handler_cb(struct msgb * msg);
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg);
// use if we have a combined uplink (RACH, SDCCH, ...) (see http://www.rfwireless-world.com/Terminology/GSM-combined-channel-configuration.html)
// if we have no combined channel config, uplink consists of only RACH
@ -54,10 +54,10 @@ static uint8_t rach_to_t3_comb[27] = {
*
* @param [in] msg the msg to sent over virtual um.
*/
static void virt_l1_sched_handler_cb(struct msgb * msg)
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg)
{
gsmtapl1_tx_to_virt_um(msg);
l1ctl_tx_rach_conf(l1_model_ms->state->current_time.fn,
gsmtapl1_tx_to_virt_um(fn, msg);
l1ctl_tx_rach_conf(fn,
l1_model_ms->state->serving_cell.arfcn);
}

View File

@ -37,19 +37,19 @@
#include <l1ctl_proto.h>
static struct l1_model_ms *l1_model_ms = NULL;
static void virt_l1_sched_handler_cb(struct msgb * msg);
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg);
/**
* @brief Handler callback function for TRAFFIC request.
*
* @param [in] msg the msg to sent over virtual um.
*/
static void virt_l1_sched_handler_cb(struct msgb * msg)
static void virt_l1_sched_handler_cb(uint32_t fn, struct msgb * msg)
{
gsmtapl1_tx_to_virt_um(msg);
gsmtapl1_tx_to_virt_um(fn, msg);
// send confirm to layer23
msg = l1ctl_create_l2_msg(L1CTL_TRAFFIC_CONF,
l1_model_ms->state->current_time.fn, 0, 0);
fn, 0, 0);
l1ctl_sap_tx_to_l23(msg);
}
@ -68,11 +68,10 @@ void l1ctl_rx_traffic_req(struct msgb *msg)
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
struct l1ctl_traffic_req *tr = (struct l1ctl_traffic_req *)ul->payload;
// TODO: calc the scheduled fn
uint32_t fn_sched = l1_model_ms->state->current_time.fn;
uint8_t rsl_chantype, subslot, timeslot;
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
uint32_t fn_sched = sched_fn_ul(l1_model_ms->state->current_time, ul->chan_nr, ul->link_id);
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
DEBUGP(DL1C, "Received and handled from l23 - L1CTL_TRAFFIC_REQ\n");
msg->l2h = tr->data;