summaryrefslogtreecommitdiffstats
path: root/src/host/virt_phy/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/virt_phy/src')
-rw-r--r--src/host/virt_phy/src/Makefile.am31
-rw-r--r--src/host/virt_phy/src/gsmtapl1_if.c213
-rw-r--r--src/host/virt_phy/src/l1ctl_sap.c193
-rw-r--r--src/host/virt_phy/src/l1ctl_sock.c15
l---------src/host/virt_phy/src/l1gprs.c1
-rw-r--r--src/host/virt_phy/src/logging.c120
-rw-r--r--src/host/virt_phy/src/shared/osmo_mcast_sock.c12
-rw-r--r--src/host/virt_phy/src/shared/virtual_um.c83
-rw-r--r--src/host/virt_phy/src/virt_l1_model.c7
-rw-r--r--src/host/virt_phy/src/virt_l1_sched_simple.c19
-rw-r--r--src/host/virt_phy/src/virt_prim_data.c29
-rw-r--r--src/host/virt_phy/src/virt_prim_fbsb.c13
-rw-r--r--src/host/virt_phy/src/virt_prim_pdch.c108
-rw-r--r--src/host/virt_phy/src/virt_prim_pm.c56
-rw-r--r--src/host/virt_phy/src/virt_prim_rach.c40
-rw-r--r--src/host/virt_phy/src/virt_prim_traffic.c39
-rw-r--r--src/host/virt_phy/src/virtphy.c52
17 files changed, 531 insertions, 500 deletions
diff --git a/src/host/virt_phy/src/Makefile.am b/src/host/virt_phy/src/Makefile.am
index bfd0dfaa..f10639f5 100644
--- a/src/host/virt_phy/src/Makefile.am
+++ b/src/host/virt_phy/src/Makefile.am
@@ -1,11 +1,28 @@
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
-AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_srcdir)/../layer23/include
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
bin_PROGRAMS = virtphy
-virtphy_SOURCES = virtphy.c l1ctl_sock.c gsmtapl1_if.c l1ctl_sap.c virt_prim_pm.c virt_prim_fbsb.c virt_prim_rach.c virt_prim_data.c virt_prim_traffic.c virt_l1_sched_simple.c logging.c virt_l1_model.c shared/virtual_um.c shared/osmo_mcast_sock.c
-virtphy_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
-virtphy_LDFLAGS = -pthread
-# debug output
-all:
- $(info $$AM_CPPFLAGS is [${AM_CPPFLAGS}])
+virtphy_SOURCES = \
+ virtphy.c \
+ l1gprs.c \
+ logging.c \
+ gsmtapl1_if.c \
+ l1ctl_sock.c \
+ l1ctl_sap.c \
+ virt_prim_pm.c \
+ virt_prim_fbsb.c \
+ virt_prim_rach.c \
+ virt_prim_data.c \
+ virt_prim_pdch.c \
+ virt_prim_traffic.c \
+ virt_l1_sched_simple.c \
+ virt_l1_model.c \
+ shared/virtual_um.c \
+ shared/osmo_mcast_sock.c \
+ $(NULL)
+
+virtphy_LDADD = \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
+ $(NULL)
diff --git a/src/host/virt_phy/src/gsmtapl1_if.c b/src/host/virt_phy/src/gsmtapl1_if.c
index 2cf9d2dc..ef8d6840 100644
--- a/src/host/virt_phy/src/gsmtapl1_if.c
+++ b/src/host/virt_phy/src/gsmtapl1_if.c
@@ -20,25 +20,28 @@
*
*/
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
#include <osmocom/core/gsmtap.h>
#include <osmocom/core/gsmtap_util.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/core/msgb.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <l1ctl_proto.h>
-#include <virtphy/virtual_um.h>
-#include <virtphy/l1ctl_sock.h>
-#include <virtphy/virt_l1_model.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <virtphy/logging.h>
-#include <virtphy/virt_l1_sched.h>
+
+#include <osmocom/bb/virtphy/virtual_um.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/l1ctl_proto.h>
static char *pseudo_lchan_name(uint16_t arfcn, uint8_t ts, uint8_t ss, uint8_t sub_type)
{
@@ -48,6 +51,29 @@ static char *pseudo_lchan_name(uint16_t arfcn, uint8_t ts, uint8_t ss, uint8_t s
return lname;
}
+/* Return gsmtap_um_voice_type or -1 on error */
+static int get_um_voice_type(enum gsm48_chan_mode tch_mode, uint8_t rsl_chantype)
+{
+ switch (tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ switch (rsl_chantype) {
+ case RSL_CHAN_Bm_ACCHs:
+ return GSMTAP_UM_VOICE_FR;
+ case RSL_CHAN_Lm_ACCHs:
+ return GSMTAP_UM_VOICE_HR;
+ default:
+ return -1;
+ }
+ break;
+ case GSM48_CMODE_SPEECH_EFR:
+ return GSMTAP_UM_VOICE_EFR;
+ case GSM48_CMODE_SPEECH_AMR:
+ return GSMTAP_UM_VOICE_AMR;
+ default:
+ return -1;
+ }
+}
+
/**
* Replace l11 header of given msgb by a gsmtap header and send it over the virt um.
*/
@@ -57,8 +83,8 @@ void gsmtapl1_tx_to_virt_um_inst(struct l1_model_ms *ms, uint32_t fn, uint8_t tn
struct l1ctl_info_ul *ul;
struct gsmtap_hdr *gh;
struct msgb *outmsg; /* msg to send with gsmtap header prepended */
- uint16_t arfcn = ms->state.serving_cell.arfcn; /* arfcn of the cell we currently camp on */
- uint8_t signal_dbm = 63; /* signal strength */
+ uint16_t arfcn;
+ uint8_t signal_dbm = rxlev2dbm(63); /* signal strength */
uint8_t snr = 63; /* signal noise ratio, 63 is best */
uint8_t *data = msgb_l2(msg); /* data to transmit (whole message without l1 header) */
uint8_t data_len = msgb_l2len(msg); /* length of data */
@@ -68,18 +94,34 @@ void gsmtapl1_tx_to_virt_um_inst(struct l1_model_ms *ms, uint32_t fn, uint8_t tn
uint8_t timeslot; /* tdma timeslot to send in (0-7) */
uint8_t gsmtap_chan; /* the gsmtap channel */
+ if (ms->state.state == MS_STATE_DEDICATED)
+ arfcn = ms->state.dedicated.band_arfcn;
+ else
+ arfcn = ms->state.serving_cell.arfcn;
+
switch (l1h->msg_type) {
- case L1CTL_DATA_TBF_REQ:
- ul = NULL;
- rsl_chantype = RSL_CHAN_OSMO_PDCH;
+ case L1CTL_GPRS_UL_BLOCK_REQ:
+ gsmtap_chan = GSMTAP_CHANNEL_PDCH;
timeslot = tn;
subslot = 0;
- gsmtap_chan = chantype_rsl2gsmtap(rsl_chantype, 0);
+ break;
+ case L1CTL_TRAFFIC_REQ:
+ ul = (struct l1ctl_info_ul *)l1h->data;
+ rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
+ gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, 0, true);
+ /* the first byte indicates the type of voice codec (gsmtap_um_voice_type);
+ * let's first strip any data in front of the l2 header, then push this extra
+ * byte to the front and finally adjust the l2h pointer */
+ msgb_pull_to_l2(msg);
+ msgb_push_u8(msg, get_um_voice_type(ms->state.tch_mode, rsl_chantype));
+ msg->l2h = msg->data;
+ data = msgb_l2(msg);
+ data_len = msgb_l2len(msg);
break;
default:
ul = (struct l1ctl_info_ul *)l1h->data;
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
- gsmtap_chan = chantype_rsl2gsmtap(rsl_chantype, ul->link_id);
+ gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, ul->link_id, false);
break;
}
@@ -116,100 +158,34 @@ extern void prim_fbsb_sync(struct l1_model_ms *ms, struct msgb *msg);
*/
extern uint16_t prim_pm_set_sig_strength(struct l1_model_ms *ms, uint16_t arfcn, int16_t sig_lev);
-/* determine if a received Downlink RLC/MAC block matches the current MS configuration */
-static bool gprs_dl_block_matches_ms(struct l1_model_ms *ms, struct msgb *msg, uint8_t timeslot)
-{
- uint8_t payload_type;
- uint8_t tfi;
-
- if (msgb_length(msg) < 1)
- return false;
-
- /* FIXME: Ensure this will also work for EGPRS! */
- payload_type = msg->data[0] >> 6;
- switch (payload_type) {
- case 0: /* RLC Data Block */
- /* forward all RLD Data Blocks destined for TFI of MS */
- tfi = (msg->data[1] >> 1) & 0x1f;
- if (ms->state.state == MS_STATE_TBF && ms->state.tbf.dl.tfi[timeslot] == tfi)
- return true;
- break;
- case 1: /* RLC/MAC Control without optional octets */
- /* forward all RLC/MAC control blocks without optional octets, i.e. not adressed
- * to a specific TFI */
- return true;
- case 2: /* RLC/MAC with optional control octets */
- /* forward all RLD Control Blocks destined for TFI of MS */
- tfi = (msg->data[2] >> 1) & 0x1f;
- if (ms->state.state == MS_STATE_TBF && ms->state.tbf.dl.tfi[timeslot] == tfi)
- return true;
- break;
- default:
- break;
- }
- return false;
-}
-
-/* determine if given USF at given timeslot is relevant to given MS or not */
-static bool usf_matches_ms(struct l1_model_ms *ms, uint8_t usf, uint8_t timeslot)
-{
- if (ms->state.state == MS_STATE_TBF && ms->state.tbf.ul.usf[timeslot] == usf)
- return true;
-
- return false;
-}
-
-/* extract USF from (E)GPRS RLC/MAC block */
-static uint8_t get_usf_from_block(struct msgb *msg)
-{
- /* FIXME: Ensure this will also work for EGPRS! */
- return msg->data[0] & 0x7;
-}
-
-/* MS is authorized to transmit a block in uplink for given USF on timeslot+arfcn at FN */
-static void ms_ul_tbf_may_transmit(struct l1_model_ms *ms, uint16_t arfcn, uint8_t timeslot,
- uint32_t fn, uint8_t usf)
-{
- struct msgb *msg;
-
- /* If USF is not for us, bail out */
- if (!usf_matches_ms(ms, usf, timeslot))
- return;
-
- /* attempt to de-queue pending msgb for this UL TBF and transmit it */
- msg = msgb_dequeue(&ms->state.tbf.ul.tx_queue);
- if (!msg) {
- printf("FN=%u, TN=%u, USF=%u: empty tx_queue, not transmitting\n", fn, timeslot, usf);
- /* FIXME: send some dummy control frame? */
- } else {
- printf("FN=%u, TN=%u, USF=%u: transmitting queued msg\n", fn, timeslot, usf);
- gsmtapl1_tx_to_virt_um_inst(ms, fn, timeslot, msg);
- }
-}
-
static void l1ctl_from_virt_um(struct l1ctl_sock_client *lsc, struct msgb *msg, uint32_t fn,
uint16_t arfcn, uint8_t timeslot, uint8_t subslot,
uint8_t gsmtap_chantype, uint8_t chan_nr, uint8_t link_id,
uint8_t snr_db)
{
struct l1_model_ms *ms = lsc->priv;
- uint8_t signal_dbm = dbm2rxlev(prim_pm_set_sig_strength(ms, arfcn & GSMTAP_ARFCN_MASK, MAX_SIG_LEV_DBM)); /* Power measurement with each received massage */
- uint8_t usf;
+ uint8_t rxlev = dbm2rxlev(prim_pm_set_sig_strength(ms, arfcn & GSMTAP_ARFCN_MASK, MAX_SIG_LEV_DBM));
gsm_fn2gsmtime(&ms->state.downlink_time, fn);
- /* we do not forward messages to l23 if we are in network search state */
- if (ms->state.state == MS_STATE_IDLE_SEARCHING)
+ switch (ms->state.state) {
+ case MS_STATE_IDLE_SEARCHING:
+ /* we do not forward messages to l23 if we are in network search state */
return;
-
- /* forward downlink msg to fbsb sync routine if we are in sync state */
- if (ms->state.state == MS_STATE_IDLE_SYNCING) {
+ case MS_STATE_IDLE_SYNCING:
+ /* forward downlink msg to fbsb sync routine if we are in sync state */
prim_fbsb_sync(ms, msg);
return;
- }
- /* generally ignore all messages coming from another arfcn than the camped one */
- if (ms->state.serving_cell.arfcn != arfcn) {
- return;
+ case MS_STATE_DEDICATED:
+ /* generally ignore all messages coming from another arfcn than the camped one */
+ if (arfcn != ms->state.dedicated.band_arfcn)
+ return;
+ break;
+ default:
+ /* generally ignore all messages coming from another arfcn than the camped one */
+ if (arfcn != ms->state.serving_cell.arfcn)
+ return;
+ break;
}
virt_l1_sched_sync_time(ms, ms->state.downlink_time, 0);
@@ -219,44 +195,49 @@ static void l1ctl_from_virt_um(struct l1ctl_sock_client *lsc, struct msgb *msg,
switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) {
case GSMTAP_CHANNEL_TCH_H:
case GSMTAP_CHANNEL_TCH_F:
-#if 0
- /* TODO: handle voice */
- if (!facch && !tch_acch) {
- l1ctl_tx_traffic_ind(msg, arfcn, link_id, chan_nr, fn,
- snr, signal_dbm, 0, 0);
- }
-#endif
+ /* This is TCH signalling, for voice frames see GSMTAP_CHANNEL_VOICE */
case GSMTAP_CHANNEL_SDCCH4:
case GSMTAP_CHANNEL_SDCCH8:
/* only forward messages on dedicated channels to l2, if
* the timeslot and subslot is fitting */
if (ms->state.dedicated.tn == timeslot
&& ms->state.dedicated.subslot == subslot) {
- l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, signal_dbm, 0, 0);
+ l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, rxlev, 0, 0);
}
break;
+ case GSMTAP_CHANNEL_VOICE_F:
+ case GSMTAP_CHANNEL_VOICE_H:
+ /* only forward messages on dedicated channels to l2, if
+ * the timeslot and subslot is fitting */
+ if (ms->state.dedicated.tn == timeslot
+ && ms->state.dedicated.subslot == subslot) {
+ l1ctl_tx_traffic_ind(ms, msg, arfcn, link_id, chan_nr, fn,
+ snr_db, rxlev, 0, 0);
+ }
+ break;
+ case GSMTAP_CHANNEL_CBCH51:
+ /* only pass CBCH data if the user application actually indicated that a CBCH
+ * is present */
+ if (ms->state.serving_cell.ccch_mode != CCCH_MODE_COMBINED_CBCH)
+ break;
case GSMTAP_CHANNEL_AGCH:
case GSMTAP_CHANNEL_PCH:
case GSMTAP_CHANNEL_BCCH:
- case GSMTAP_CHANNEL_CBCH51:
case GSMTAP_CHANNEL_CBCH52:
/* save to just forward here, as upper layer ignores messages that
* do not fit the current state (e.g. gsm48_rr.c:2159) */
- l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, signal_dbm, 0, 0);
+ l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, rxlev, 0, 0);
break;
case GSMTAP_CHANNEL_RACH:
LOGPMS(DVIRPHY, LOGL_NOTICE, ms, "Ignoring unexpected RACH in downlink ?!?\n");
break;
+ case GSMTAP_CHANNEL_PTCCH:
case GSMTAP_CHANNEL_PACCH:
case GSMTAP_CHANNEL_PDCH:
- if (gprs_dl_block_matches_ms(ms, msg, timeslot))
- l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, signal_dbm, 0, 0);
- usf = get_usf_from_block(msg);
- ms_ul_tbf_may_transmit(ms, arfcn, timeslot, fn, usf);
+ l1ctl_tx_gprs_dl_block_ind(ms, msg, fn, timeslot, rxlev);
break;
case GSMTAP_CHANNEL_SDCCH:
case GSMTAP_CHANNEL_CCCH:
- case GSMTAP_CHANNEL_PTCCH:
LOGPMS(DVIRPHY, LOGL_NOTICE, ms, "Ignoring unsupported channel type %s\n",
get_value_string(gsmtap_gsm_channel_names, gsmtap_chantype));
break;
diff --git a/src/host/virt_phy/src/l1ctl_sap.c b/src/host/virt_phy/src/l1ctl_sap.c
index f95a4caf..7e4540df 100644
--- a/src/host/virt_phy/src/l1ctl_sap.c
+++ b/src/host/virt_phy/src/l1ctl_sap.c
@@ -19,6 +19,9 @@
*
*/
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
@@ -27,21 +30,16 @@
#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/rsl.h>
-#include <osmocom/gprs/gprs_rlc.h>
-#include <stdio.h>
-#include <l1ctl_proto.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <virtphy/virtual_um.h>
-#include <virtphy/l1ctl_sock.h>
-#include <virtphy/virt_l1_model.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <virtphy/logging.h>
-#include <virtphy/virt_l1_sched.h>
-static void l1ctl_rx_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg);
-static void l1ctl_rx_data_tbf_req(struct l1_model_ms *ms, struct msgb *msg);
+#include <osmocom/bb/virtphy/virtual_um.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/l1ctl_proto.h>
+#include <osmocom/bb/l1gprs.h>
static void l1_model_tch_mode_set(struct l1_model_ms *ms, uint8_t tch_mode)
{
@@ -59,7 +57,6 @@ static void l1_model_tch_mode_set(struct l1_model_ms *ms, uint8_t tch_mode)
void l1ctl_sap_init(struct l1_model_ms *model)
{
INIT_LLIST_HEAD(&model->state.sched.mframe_items);
- INIT_LLIST_HEAD(&model->state.tbf.ul.tx_queue);
prim_pm_init(model);
}
@@ -162,8 +159,8 @@ static bool is_l1ctl_control(uint8_t msg_type)
switch (msg_type) {
case L1CTL_DATA_REQ:
case L1CTL_DATA_CONF:
- case L1CTL_DATA_TBF_REQ:
- case L1CTL_DATA_TBF_CONF:
+ case L1CTL_GPRS_UL_BLOCK_REQ:
+ case L1CTL_GPRS_DL_BLOCK_IND:
case L1CTL_TRAFFIC_REQ:
case L1CTL_TRAFFIC_CONF:
case L1CTL_TRAFFIC_IND:
@@ -246,11 +243,12 @@ void l1ctl_sap_handler(struct l1_model_ms *ms, struct msgb *msg)
case L1CTL_SIM_REQ:
l1ctl_rx_sim_req(ms, msg);
break;
- case L1CTL_TBF_CFG_REQ:
- l1ctl_rx_tbf_cfg_req(ms, msg);
+ case L1CTL_GPRS_UL_TBF_CFG_REQ:
+ case L1CTL_GPRS_DL_TBF_CFG_REQ:
+ l1ctl_rx_gprs_uldl_tbf_cfg_req(ms, msg);
break;
- case L1CTL_DATA_TBF_REQ:
- l1ctl_rx_data_tbf_req(ms, msg);
+ case L1CTL_GPRS_UL_BLOCK_REQ:
+ l1ctl_rx_gprs_ul_block_req(ms, msg);
goto exit_nofree;
}
@@ -286,14 +284,22 @@ void l1ctl_rx_dm_est_req(struct l1_model_ms *ms, struct msgb *msg)
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
- LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_DM_EST_REQ (chan_nr=0x%02x, tn=%u, ss=%u)\n",
- ul->chan_nr, timeslot, subslot);
+ LOGPMS(DL1C, LOGL_DEBUG, ms, "Rx L1CTL_DM_EST_REQ (chan_nr=0x%02x, arfcn=%u, tn=%u, ss=%u)\n",
+ ul->chan_nr, ntohs(est_req->h0.band_arfcn), timeslot, subslot);
+ OSMO_ASSERT(est_req->h == 0); /* we don't do hopping */
+ ms->state.dedicated.band_arfcn = ntohs(est_req->h0.band_arfcn);
ms->state.dedicated.chan_type = rsl_chantype;
ms->state.dedicated.tn = timeslot;
ms->state.dedicated.subslot = subslot;
ms->state.state = MS_STATE_DEDICATED;
+ if (rsl_chantype == RSL_CHAN_OSMO_PDCH) {
+ OSMO_ASSERT(ms->gprs == NULL);
+ ms->gprs = l1gprs_state_alloc(ms, NULL, ms);
+ OSMO_ASSERT(ms->gprs != NULL);
+ }
+
/* TCH config */
if (rsl_chantype == RSL_CHAN_Bm_ACCHs || rsl_chantype == RSL_CHAN_Lm_ACCHs) {
ms->state.tch_mode = est_req->tch_mode;
@@ -313,7 +319,7 @@ void l1ctl_rx_dm_est_req(struct l1_model_ms *ms, struct msgb *msg)
*
* Handle frequency change in dedicated mode. E.g. used for frequency hopping.
*
- * Note: Not needed for virtual physical layer as freqency hopping is generally disabled.
+ * Note: Not needed for virtual physical layer as frequency hopping is generally disabled.
*/
void l1ctl_rx_dm_freq_req(struct l1_model_ms *ms, struct msgb *msg)
{
@@ -378,6 +384,9 @@ void l1ctl_rx_dm_rel_req(struct l1_model_ms *ms, struct msgb *msg)
ms->state.tch_mode = GSM48_CMODE_SIGN;
ms->state.state = MS_STATE_IDLE_CAMPING;
+ l1gprs_state_free(ms->gprs);
+ ms->gprs = NULL;
+
/* TODO: disable ciphering */
/* TODO: disable audio recording / playing */
}
@@ -426,6 +435,8 @@ void l1ctl_rx_reset_req(struct l1_model_ms *ms, struct msgb *msg)
DEBUGPMS(DL1C, ms, "Rx L1CTL_RESET_REQ (type=FULL)\n");
ms->state.state = MS_STATE_IDLE_SEARCHING;
virt_l1_sched_stop(ms);
+ l1gprs_state_free(ms->gprs);
+ ms->gprs = NULL;
l1ctl_tx_reset(ms, L1CTL_RESET_CONF, reset_req->type);
break;
case L1CTL_RES_T_SCHED:
@@ -484,6 +495,7 @@ void l1ctl_rx_tch_mode_req(struct l1_model_ms *ms, struct msgb *msg)
l1_model_tch_mode_set(ms, tch_mode_req->tch_mode);
ms->state.audio_mode = tch_mode_req->audio_mode;
+ /* TODO: Handle AMR codecs from tch_mode_req if tch_mode_req->tch_mode==GSM48_CMODE_SPEECH_AMR */
LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_TCH_MODE_REQ (tch_mode=0x%02x audio_mode=0x%02x)\n",
tch_mode_req->tch_mode, tch_mode_req->audio_mode);
@@ -504,7 +516,7 @@ void l1ctl_rx_tch_mode_req(struct l1_model_ms *ms, struct msgb *msg)
* The neighbor cell description is one of the info messages sent by the BTS on BCCH.
* This method will also enable neighbor measurement in the multiframe scheduler.
*
- * Note: Not needed for virtual physical layer as we dont maintain neigbors.
+ * Note: Not needed for virtual physical layer as we don't maintain neighbors.
*/
void l1ctl_rx_neigh_pm_req(struct l1_model_ms *ms, struct msgb *msg)
{
@@ -543,143 +555,12 @@ void l1ctl_rx_sim_req(struct l1_model_ms *ms, struct msgb *msg)
}
-static void l1ctl_tx_tbf_cfg_conf(struct l1_model_ms *ms, const struct l1ctl_tbf_cfg_req *in);
-
-static void l1ctl_rx_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_tbf_cfg_req *cfg_req = (struct l1ctl_tbf_cfg_req *) l1h->data;
- unsigned int i;
-
- LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_TBF_CFG_REQ (tbf_id=%u, dir=%s, "
- "usf=[%d,%d,%d,%d,%d,%d,%d,%d]\n", cfg_req->tbf_nr,
- cfg_req->is_uplink ? "UL" : "DL", cfg_req->usf[0], cfg_req->usf[1],
- cfg_req->usf[2], cfg_req->usf[3], cfg_req->usf[4], cfg_req->usf[5],
- cfg_req->usf[6], cfg_req->usf[7]);
-
- if (cfg_req->tbf_nr != 0) {
- LOGPMS(DL1C, LOGL_ERROR, ms, "TBF_NR != 0 not supported yet!\n");
- return;
- }
-
- if (ms->state.state == MS_STATE_DEDICATED)
- LOGPMS(DL1C, LOGL_NOTICE, ms, "Hard termination of DEDICATED mode, fix L23!\n");
-
- if (cfg_req->is_uplink) {
- for (i = 0; i < 8; i++)
- ms->state.tbf.ul.usf[i] = cfg_req->usf[i];
- } else {
- for (i = 0; i < 8; i++)
- ms->state.tbf.dl.tfi[i] = cfg_req->usf[i];
- }
- ms->state.state = MS_STATE_TBF;
-
- l1ctl_tx_tbf_cfg_conf(ms, cfg_req);
-}
-
-static const enum osmo_gprs_cs osmo_cs_by_l1ctl[] = {
- [L1CTL_CS_NONE] = OSMO_GPRS_CS_NONE,
- [L1CTL_CS1] = OSMO_GPRS_CS1,
- [L1CTL_CS2] = OSMO_GPRS_CS2,
- [L1CTL_CS3] = OSMO_GPRS_CS3,
- [L1CTL_CS4] = OSMO_GPRS_CS4,
- [L1CTL_MCS1] = OSMO_GPRS_MCS1,
- [L1CTL_MCS2] = OSMO_GPRS_MCS2,
- [L1CTL_MCS3] = OSMO_GPRS_MCS3,
- [L1CTL_MCS4] = OSMO_GPRS_MCS4,
- [L1CTL_MCS5] = OSMO_GPRS_MCS5,
- [L1CTL_MCS6] = OSMO_GPRS_MCS6,
- [L1CTL_MCS7] = OSMO_GPRS_MCS7,
- [L1CTL_MCS8] = OSMO_GPRS_MCS8,
- [L1CTL_MCS9] = OSMO_GPRS_MCS9,
-};
-
-static int get_osmo_cs_by_l1ctl(enum l1ctl_coding_scheme l1)
-{
- if (l1 >= ARRAY_SIZE(osmo_cs_by_l1ctl))
- return -1;
- return osmo_cs_by_l1ctl[l1];
-}
-
-static const enum l1ctl_coding_scheme l1ctl_cs_by_osmo[] = {
- [OSMO_GPRS_CS_NONE] = L1CTL_CS_NONE,
- [OSMO_GPRS_CS1] = L1CTL_CS1,
- [OSMO_GPRS_CS2] = L1CTL_CS2,
- [OSMO_GPRS_CS3] = L1CTL_CS3,
- [OSMO_GPRS_CS4] = L1CTL_CS4,
- [OSMO_GPRS_MCS1] = L1CTL_MCS1,
- [OSMO_GPRS_MCS2] = L1CTL_MCS2,
- [OSMO_GPRS_MCS3] = L1CTL_MCS3,
- [OSMO_GPRS_MCS4] = L1CTL_MCS4,
- [OSMO_GPRS_MCS5] = L1CTL_MCS5,
- [OSMO_GPRS_MCS6] = L1CTL_MCS6,
- [OSMO_GPRS_MCS7] = L1CTL_MCS7,
- [OSMO_GPRS_MCS8] = L1CTL_MCS8,
- [OSMO_GPRS_MCS9] = L1CTL_MCS9,
-};
-
-static int get_l1ctl_cs_by_osmo(enum osmo_gprs_cs in)
-{
- if (in >= ARRAY_SIZE(l1ctl_cs_by_osmo))
- return -1;
- return l1ctl_cs_by_osmo[in];
-}
-
-static void l1ctl_rx_data_tbf_req(struct l1_model_ms *ms, struct msgb *msg)
-{
- struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
- struct l1ctl_info_ul_tbf *udt = (struct l1ctl_info_ul_tbf *) l1h->data;
- enum osmo_gprs_cs osmo_cs;
- int block_size;
-
- msg->l2h = udt->payload;
-
- LOGPMS(DL1P, LOGL_ERROR, ms, "Rx L1CTL_DATA_TBF_REQ (tbf_id=%d, data=%s)\n",
- udt->tbf_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
- if (udt->tbf_nr != 0) {
- LOGPMS(DL1C, LOGL_ERROR, ms, "TBF_NR != 0 not supported yet!\n");
- return;
- }
-
- if (ms->state.state != MS_STATE_TBF) {
- LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_TBF_REQ in state != TBF\n");
- return;
- }
-
- osmo_cs = get_l1ctl_cs_by_osmo(udt->coding_scheme);
- if (osmo_cs < 0) {
- LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_RBF_REQ with invalid CS\n");
- return;
- }
- block_size = osmo_gprs_ul_block_size_bytes(osmo_cs);
-
- if (msgb_l2len(msg) < block_size) {
- int pad_len = block_size - msgb_l2len(msg);
- uint8_t *pad = msgb_put(msg, pad_len);
- memset(pad, GSM_MACBLOCK_PADDING, pad_len);
- }
-
- msgb_enqueue(&ms->state.tbf.ul.tx_queue, msg);
-}
-
/***************************************************************
* L1CTL TX ROUTINES *******************************************
* For more routines check the respective handler classes ******
* like virt_prim_rach.c ***************************************
***************************************************************/
-static void l1ctl_tx_tbf_cfg_conf(struct l1_model_ms *ms, const struct l1ctl_tbf_cfg_req *in)
-{
- struct msgb *msg = l1ctl_msgb_alloc(L1CTL_TBF_CFG_CONF);
- struct l1ctl_tbf_cfg_req *out;
-
- /* copy over the data from the request */
- out = (struct l1ctl_tbf_cfg_req *) msgb_put(msg, sizeof(*out));
- *out = *in;
-
- l1ctl_sap_tx_to_l23_inst(ms, msg);
-}
-
/**
* @brief Transmit L1CTL_RESET_IND or L1CTL_RESET_CONF to layer 23.
*
diff --git a/src/host/virt_phy/src/l1ctl_sock.c b/src/host/virt_phy/src/l1ctl_sock.c
index bf28895f..089d9caf 100644
--- a/src/host/virt_phy/src/l1ctl_sock.c
+++ b/src/host/virt_phy/src/l1ctl_sock.c
@@ -40,8 +40,8 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/socket.h>
-#include <virtphy/l1ctl_sock.h>
-#include <virtphy/logging.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+#include <osmocom/bb/virtphy/logging.h>
#define L1CTL_SOCK_MSGB_SIZE 256
@@ -72,7 +72,7 @@ static int l1ctl_sock_data_cb(struct osmo_fd *ofd, unsigned int what)
int rc;
/* Check if request is really read request */
- if (!(what & BSC_FD_READ))
+ if (!(what & OSMO_FD_READ))
return 0;
msg = msgb_alloc(L1CTL_SOCK_MSGB_SIZE, "L1CTL sock rx");
@@ -125,10 +125,7 @@ static int l1ctl_sock_accept_cb(struct osmo_fd *ofd, unsigned int what)
}
lsc->l1ctl_sock = lsi;
- lsc->ofd.fd = fd;
- lsc->ofd.when = BSC_FD_READ;
- lsc->ofd.cb = l1ctl_sock_data_cb;
- lsc->ofd.data = lsc;
+ osmo_fd_setup(&lsc->ofd, fd, OSMO_FD_READ, l1ctl_sock_data_cb, lsc, 0);
if (lsi->accept_cb) {
rc = lsi->accept_cb(lsc);
if (rc < 0) {
@@ -163,9 +160,7 @@ struct l1ctl_sock_inst *l1ctl_sock_init(
lsi = talloc_zero(ctx, struct l1ctl_sock_inst);
lsi->priv = NULL;
- lsi->ofd.data = lsi;
- lsi->ofd.when = BSC_FD_READ;
- lsi->ofd.cb = l1ctl_sock_accept_cb;
+ osmo_fd_setup(&lsi->ofd, -1, OSMO_FD_READ, l1ctl_sock_accept_cb, lsi, 0);
rc = osmo_sock_unix_init_ofd(&lsi->ofd, SOCK_STREAM, 0, path, OSMO_SOCK_F_BIND);
if (rc < 0) {
diff --git a/src/host/virt_phy/src/l1gprs.c b/src/host/virt_phy/src/l1gprs.c
new file mode 120000
index 00000000..0185f68b
--- /dev/null
+++ b/src/host/virt_phy/src/l1gprs.c
@@ -0,0 +1 @@
+../../../shared/l1gprs.c \ No newline at end of file
diff --git a/src/host/virt_phy/src/logging.c b/src/host/virt_phy/src/logging.c
index 7e4e79b1..fc37205f 100644
--- a/src/host/virt_phy/src/logging.c
+++ b/src/host/virt_phy/src/logging.c
@@ -15,53 +15,49 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <osmocom/core/utils.h>
#include <osmocom/core/application.h>
-#include <virtphy/logging.h>
+#include <osmocom/bb/virtphy/logging.h>
static const char* l1ctlPrimNames[] = {
- "_L1CTL_NONE",
- "L1CTL_FBSB_REQ",
- "L1CTL_FBSB_CONF",
- "L1CTL_DATA_IND",
- "L1CTL_RACH_REQ",
- "L1CTL_DM_EST_REQ",
- "L1CTL_DATA_REQ",
- "L1CTL_RESET_IND",
- "L1CTL_PM_REQ",
- "L1CTL_PM_CONF",
- "L1CTL_ECHO_REQ",
- "L1CTL_ECHO_CONF",
- "L1CTL_RACH_CONF",
- "L1CTL_RESET_REQ",
- "L1CTL_RESET_CONF",
- "L1CTL_DATA_CONF",
- "L1CTL_CCCH_MODE_REQ",
- "L1CTL_CCCH_MODE_CONF",
- "L1CTL_DM_REL_REQ",
- "L1CTL_PARAM_REQ",
- "L1CTL_DM_FREQ_REQ",
- "L1CTL_CRYPTO_REQ",
- "L1CTL_SIM_REQ",
- "L1CTL_SIM_CONF",
- "L1CTL_TCH_MODE_REQ",
- "L1CTL_TCH_MODE_CONF",
- "L1CTL_NEIGH_PM_REQ",
- "L1CTL_NEIGH_PM_IND",
- "L1CTL_TRAFFIC_REQ",
- "L1CTL_TRAFFIC_CONF",
- "L1CTL_TRAFFIC_IND",
- "L1CTL_BURST_IND",
- "L1CTL_TBF_CFG_REQ",
- "L1CTL_TBF_CFG_CONF",
- "L1CTL_DATA_TBF_REQ",
- "L1CTL_DATA_TBF_CONF"
+ "_L1CTL_NONE",
+ "L1CTL_FBSB_REQ",
+ "L1CTL_FBSB_CONF",
+ "L1CTL_DATA_IND",
+ "L1CTL_RACH_REQ",
+ "L1CTL_DM_EST_REQ",
+ "L1CTL_DATA_REQ",
+ "L1CTL_RESET_IND",
+ "L1CTL_PM_REQ",
+ "L1CTL_PM_CONF",
+ "L1CTL_ECHO_REQ",
+ "L1CTL_ECHO_CONF",
+ "L1CTL_RACH_CONF",
+ "L1CTL_RESET_REQ",
+ "L1CTL_RESET_CONF",
+ "L1CTL_DATA_CONF",
+ "L1CTL_CCCH_MODE_REQ",
+ "L1CTL_CCCH_MODE_CONF",
+ "L1CTL_DM_REL_REQ",
+ "L1CTL_PARAM_REQ",
+ "L1CTL_DM_FREQ_REQ",
+ "L1CTL_CRYPTO_REQ",
+ "L1CTL_SIM_REQ",
+ "L1CTL_SIM_CONF",
+ "L1CTL_TCH_MODE_REQ",
+ "L1CTL_TCH_MODE_CONF",
+ "L1CTL_NEIGH_PM_REQ",
+ "L1CTL_NEIGH_PM_IND",
+ "L1CTL_TRAFFIC_REQ",
+ "L1CTL_TRAFFIC_CONF",
+ "L1CTL_TRAFFIC_IND",
+ "L1CTL_BURST_IND",
+ "L1CTL_GPRS_UL_TBF_CFG_REQ",
+ "L1CTL_GPRS_DL_TBF_CFG_REQ",
+ "L1CTL_GPRS_UL_BLOCK_REQ",
+ "L1CTL_GPRS_DL_BLOCK_IND",
};
static const struct log_info_cat default_categories[] = {
@@ -70,28 +66,35 @@ static const struct log_info_cat default_categories[] = {
.description = "Layer 1 Control",
.color = "\033[1;31m",
.enabled = 1,
- .loglevel = LOGL_DEBUG,
+ .loglevel = LOGL_NOTICE,
},
[DL1P] = {
.name = "DL1P",
.description = "Layer 1 Data",
.color = "\033[1;31m",
.enabled = 1,
- .loglevel = LOGL_DEBUG,
+ .loglevel = LOGL_NOTICE,
},
[DVIRPHY] = {
.name = "DVIRPHY",
.description = "Virtual Layer 1 Interface",
.color = "\033[1;31m",
.enabled = 1,
- .loglevel = LOGL_DEBUG,
+ .loglevel = LOGL_NOTICE,
+ },
+ [DGPRS] = {
+ .name = "DGPRS",
+ .description = "L1 GPRS (MAC leyer)",
+ .color = "\033[1;31m",
+ .enabled = 1,
+ .loglevel = LOGL_NOTICE,
},
[DMAIN] = {
.name = "DMAIN",
.description = "Main Program / Data Structures",
.color = "\033[1;32m",
.enabled = 1,
- .loglevel = LOGL_DEBUG,
+ .loglevel = LOGL_NOTICE,
},
};
@@ -104,24 +107,21 @@ const struct log_info ms_log_info = {
/**
* Initialize the logging system for the virtual physical layer.
*/
-int ms_log_init(char *cat_mask)
+int ms_log_init(void *ctx, const char *cat_mask)
{
- struct log_target *stderr_target;
+ int rc;
- log_init(&ms_log_info, NULL);
- stderr_target = log_target_create_stderr();
- if (!stderr)
- return -1;
+ rc = osmo_init_logging2(ctx, &ms_log_info);
+ OSMO_ASSERT(rc == 0);
- log_add_target(stderr_target);
- log_set_all_filter(stderr_target, 1);
- //log_set_log_level(stderr_target, 1);
- log_set_print_filename(stderr_target, 1);
- log_set_use_color(stderr_target, 0);
- log_set_print_timestamp(stderr_target, 1);
- log_set_print_category(stderr_target, 1);
+ //log_set_log_level(osmo_stderr_target, 1);
+ log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_PATH);
+ log_set_use_color(osmo_stderr_target, 0);
+ log_set_print_timestamp(osmo_stderr_target, 1);
+ log_set_print_category_hex(osmo_stderr_target, 0);
+ log_set_print_category(osmo_stderr_target, 1);
if (cat_mask)
- log_parse_category_mask(stderr_target, cat_mask);
+ log_parse_category_mask(osmo_stderr_target, cat_mask);
return 0;
}
@@ -131,5 +131,5 @@ const char *getL1ctlPrimName(uint8_t type)
if (type < ARRAY_SIZE(l1ctlPrimNames))
return l1ctlPrimNames[type];
else
- return "Unknwon Primitive";
+ return "Unknown Primitive";
}
diff --git a/src/host/virt_phy/src/shared/osmo_mcast_sock.c b/src/host/virt_phy/src/shared/osmo_mcast_sock.c
index 9a713fcf..d3ae4fe9 100644
--- a/src/host/virt_phy/src/shared/osmo_mcast_sock.c
+++ b/src/host/virt_phy/src/shared/osmo_mcast_sock.c
@@ -1,14 +1,16 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/select.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <talloc.h>
#include <unistd.h>
-#include <virtphy/osmo_mcast_sock.h>
+
+#include <osmocom/core/socket.h>
+#include <osmocom/core/select.h>
+
+#include <osmocom/bb/virtphy/osmo_mcast_sock.h>
/* server socket is what we use for transmission. It is not subscribed
* to a multicast group or locally bound, but it is just a normal UDP
@@ -43,9 +45,7 @@ int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16
int rc;
unsigned int flags = OSMO_SOCK_F_BIND | OSMO_SOCK_F_NO_MCAST_ALL | OSMO_SOCK_F_UDP_REUSEADDR;
- ofd->cb = fd_rx_cb;
- ofd->when = BSC_FD_READ;
- ofd->data = osmo_fd_data;
+ osmo_fd_setup(ofd, -1, OSMO_FD_READ, fd_rx_cb, osmo_fd_data, 0);
/* Create mcast client socket */
rc = osmo_sock_init_ofd(ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
diff --git a/src/host/virt_phy/src/shared/virtual_um.c b/src/host/virt_phy/src/shared/virtual_um.c
index 9415bfbb..e55bb034 100644
--- a/src/host/virt_phy/src/shared/virtual_um.c
+++ b/src/host/virt_phy/src/shared/virtual_um.c
@@ -19,15 +19,18 @@
*
*/
+#include <unistd.h>
+#include <errno.h>
+
#include <osmocom/core/select.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/gsmtap.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
-#include <virtphy/osmo_mcast_sock.h>
-#include <virtphy/virtual_um.h>
-#include <unistd.h>
+
+#include <osmocom/bb/virtphy/osmo_mcast_sock.h>
+#include <osmocom/bb/virtphy/virtual_um.h>
/**
* Virtual UM interface file descriptor callback.
@@ -37,49 +40,71 @@ static int virt_um_fd_cb(struct osmo_fd *ofd, unsigned int what)
{
struct virt_um_inst *vui = ofd->data;
- // check if the read flag is set
- if (what & BSC_FD_READ) {
- // allocate message buffer of specified size
- struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE,
- "Virtual UM Rx");
+ if (what & OSMO_FD_READ) {
+ struct msgb *msg = msgb_alloc(VIRT_UM_MSGB_SIZE, "Virtual UM Rx");
int rc;
- // read message from fd in message buffer
- rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg),
- msgb_tailroom(msg));
- // rc is number of bytes actually read
+ /* read message from fd into message buffer */
+ rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg), msgb_tailroom(msg));
if (rc > 0) {
msgb_put(msg, rc);
msg->l1h = msgb_data(msg);
- // call the l1 callback function for a received msg
+ /* call the l1 callback function for a received msg */
vui->recv_cb(vui, msg);
- } else {
- // TODO: this kind of error handling might be a bit harsh
+ } else if (rc == 0) {
vui->recv_cb(vui, NULL);
- // Unregister fd from select loop
- osmo_fd_unregister(ofd);
- close(ofd->fd);
- ofd->fd = -1;
- ofd->when = 0;
- }
+ osmo_fd_close(ofd);
+ } else
+ perror("Read from multicast socket");
+
}
return 0;
}
-struct virt_um_inst *virt_um_init(
- void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port,
- char *rx_mcast_group, uint16_t rx_mcast_port,
- void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
+struct virt_um_inst *virt_um_init(void *ctx, char *tx_mcast_group, uint16_t tx_mcast_port,
+ char *rx_mcast_group, uint16_t rx_mcast_port, int ttl, const char *dev_name,
+ void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
{
struct virt_um_inst *vui = talloc_zero(ctx, struct virt_um_inst);
- vui->mcast_sock = mcast_bidir_sock_setup(ctx, tx_mcast_group,
- tx_mcast_port, rx_mcast_group, rx_mcast_port, 1,
- virt_um_fd_cb, vui);
+ int rc;
+
+ vui->mcast_sock = mcast_bidir_sock_setup(ctx, tx_mcast_group, tx_mcast_port,
+ rx_mcast_group, rx_mcast_port, 1, virt_um_fd_cb, vui);
+ if (!vui->mcast_sock) {
+ perror("Unable to create VirtualUm multicast socket");
+ talloc_free(vui);
+ return NULL;
+ }
vui->recv_cb = recv_cb;
+ if (ttl >= 0) {
+ rc = osmo_sock_mcast_ttl_set(vui->mcast_sock->tx_ofd.fd, ttl);
+ if (rc < 0) {
+ perror("Cannot set TTL of Virtual Um transmit socket");
+ goto out_close;
+ }
+ }
+
+ if (dev_name) {
+ rc = osmo_sock_mcast_iface_set(vui->mcast_sock->tx_ofd.fd, dev_name);
+ if (rc < 0) {
+ perror("Cannot bind multicast tx to given device");
+ goto out_close;
+ }
+ rc = osmo_sock_mcast_iface_set(vui->mcast_sock->rx_ofd.fd, dev_name);
+ if (rc < 0) {
+ perror("Cannot bind multicast rx to given device");
+ goto out_close;
+ }
+ }
+
return vui;
+out_close:
+ mcast_bidir_sock_close(vui->mcast_sock);
+ talloc_free(vui);
+ return NULL;
}
void virt_um_destroy(struct virt_um_inst *vui)
@@ -97,6 +122,8 @@ int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg)
rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg),
msgb_length(msg));
+ if (rc < 0)
+ rc = -errno;
msgb_free(msg);
return rc;
diff --git a/src/host/virt_phy/src/virt_l1_model.c b/src/host/virt_phy/src/virt_l1_model.c
index 5738bed6..704a54cd 100644
--- a/src/host/virt_phy/src/virt_l1_model.c
+++ b/src/host/virt_phy/src/virt_l1_model.c
@@ -19,11 +19,12 @@
*
*/
-#include <virtphy/virt_l1_model.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/logging.h>
#include <talloc.h>
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/logging.h>
+
static uint32_t next_ms_nr;
struct l1_model_ms *l1_model_ms_init(void *ctx, struct l1ctl_sock_client *lsc, struct virt_um_inst *vui)
diff --git a/src/host/virt_phy/src/virt_l1_sched_simple.c b/src/host/virt_phy/src/virt_l1_sched_simple.c
index 4737135c..3cad2ce0 100644
--- a/src/host/virt_phy/src/virt_l1_sched_simple.c
+++ b/src/host/virt_phy/src/virt_l1_sched_simple.c
@@ -18,13 +18,15 @@
*
*/
-#include <virtphy/virt_l1_sched.h>
-#include <osmocom/core/linuxlist.h>
-#include <virtphy/virt_l1_model.h>
-#include <virtphy/logging.h>
#include <time.h>
#include <talloc.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/logging.h>
+
/**
* @brief Start scheduler thread based on current gsm time from model
*/
@@ -97,6 +99,7 @@ void virt_l1_sched_execute(struct l1_model_ms *ms, uint32_t fn)
ti_next->handler_cb(ms, mi_next->fn, ti_next->ts, ti_next->msg);
/* remove handled tdma sched item */
llist_del(&ti_next->tdma_item_entry);
+ talloc_free(ti_next);
}
/* remove handled mframe sched item */
llist_del(&mi_next->mframe_item_entry);
@@ -129,12 +132,8 @@ void virt_l1_sched_schedule(struct l1_model_ms *ms, struct msgb *msg, uint32_t f
/* list did not contain mframe item with needed fn */
mi_fn = talloc_zero(ms, struct virt_l1_sched_mframe_item);
mi_fn->fn = fn;
- /* need to manually init the struct content.... no so happy */
- mi_fn->tdma_item_list.prev = &mi_fn->tdma_item_list;
- mi_fn->tdma_item_list.next = &mi_fn->tdma_item_list;
-
- /* TODO: check if we get an error if list is empty... */
- llist_add(&mi_fn->mframe_item_entry, mi_next->mframe_item_entry.prev);
+ INIT_LLIST_HEAD(&mi_fn->tdma_item_list);
+ llist_add_tail(&mi_fn->mframe_item_entry, &mi_next->mframe_item_entry);
}
ti_new = talloc_zero(mi_fn, struct virt_l1_sched_tdma_item);
diff --git a/src/host/virt_phy/src/virt_prim_data.c b/src/host/virt_phy/src/virt_prim_data.c
index 96534aab..d8897915 100644
--- a/src/host/virt_phy/src/virt_prim_data.c
+++ b/src/host/virt_phy/src/virt_prim_data.c
@@ -16,10 +16,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -31,12 +27,12 @@
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/core/msgb.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/virt_l1_sched.h>
-#include <virtphy/logging.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <l1ctl_proto.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/l1ctl_proto.h>
/**
* @brief Handler callback function for DATA request.
@@ -47,7 +43,8 @@
static void virt_l1_sched_handler_cb(struct l1_model_ms *ms, uint32_t fn, uint8_t tn, struct msgb * msg)
{
gsmtapl1_tx_to_virt_um_inst(ms, fn, tn, msg);
- l1ctl_tx_data_conf(ms, fn, 0, ms->state.serving_cell.arfcn);
+ /* FIXME: get ARFCN from msg payload */
+ l1ctl_tx_data_conf(ms, fn, 0, ms->state.dedicated.band_arfcn);
}
/**
@@ -73,15 +70,15 @@ void l1ctl_rx_data_req(struct l1_model_ms *ms, struct msgb *msg)
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
msg->l2h = data_ind->data;
- LOGPMS(DL1P, LOGL_INFO, ms, "Rx L1CTL_DATA_REQ (chan_nr=0x%02x, link_id=0x%02x) %s\n",
+ LOGPMS(DL1P, LOGL_DEBUG, ms, "Rx L1CTL_DATA_REQ (chan_nr=0x%02x, link_id=0x%02x) %s\n",
ul->chan_nr, ul->link_id, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
virt_l1_sched_schedule(ms, msg, fn_sched, timeslot, &virt_l1_sched_handler_cb);
}
void l1ctl_tx_data_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arfcn, uint8_t link_id,
- uint8_t chan_nr, uint32_t fn, uint8_t snr,
- uint8_t signal_dbm, uint8_t num_biterr, uint8_t fire_crc)
+ uint8_t chan_nr, uint32_t fn, uint8_t snr,
+ uint8_t rxlev, uint8_t num_biterr, uint8_t fire_crc)
{
struct msgb *l1ctl_msg = NULL;
struct l1ctl_data_ind * l1di;
@@ -97,7 +94,7 @@ void l1ctl_tx_data_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arfcn,
l1dl->chan_nr = chan_nr;
l1dl->frame_nr = htonl(fn);
l1dl->snr = snr;
- l1dl->rx_level = signal_dbm;
+ l1dl->rx_level = rxlev;
l1dl->num_biterr = 0; /* no biterrors */
l1dl->fire_crc = 0;
@@ -105,7 +102,7 @@ void l1ctl_tx_data_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arfcn,
memcpy(l1di->data, msgb_data(msg), msgb_length(msg));
- LOGPMS(DL1P, LOGL_INFO, ms, "TX L1CTL_DATA_IND (link_id=0x%02x) %s\n", link_id,
+ LOGPMS(DL1P, LOGL_DEBUG, ms, "TX L1CTL_DATA_IND (link_id=0x%02x) %s\n", link_id,
osmo_hexdump(msgb_data(msg), msgb_length(msg)));
l1ctl_sap_tx_to_l23_inst(ms, l1ctl_msg);
}
@@ -123,6 +120,6 @@ void l1ctl_tx_data_conf(struct l1_model_ms *ms, uint32_t fn, uint16_t snr, uint1
struct msgb * l1ctl_msg;
l1ctl_msg = l1ctl_create_l2_msg(L1CTL_DATA_CONF, fn, snr, arfcn);
/* send confirm to layer23 */
- LOGPMS(DL1P, LOGL_INFO, ms, "Tx L1CTL_DATA_CONF\n");
+ LOGPMS(DL1P, LOGL_DEBUG, ms, "Tx L1CTL_DATA_CONF\n");
l1ctl_sap_tx_to_l23_inst(ms, l1ctl_msg);
}
diff --git a/src/host/virt_phy/src/virt_prim_fbsb.c b/src/host/virt_phy/src/virt_prim_fbsb.c
index c14a4485..d012036f 100644
--- a/src/host/virt_phy/src/virt_prim_fbsb.c
+++ b/src/host/virt_phy/src/virt_prim_fbsb.c
@@ -15,10 +15,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -29,11 +25,12 @@
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/core/msgb.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/virt_l1_sched.h>
#include <osmocom/core/gsmtap.h>
-#include <virtphy/logging.h>
-#include <l1ctl_proto.h>
+
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/l1ctl_proto.h>
static uint16_t sync_count = 0;
diff --git a/src/host/virt_phy/src/virt_prim_pdch.c b/src/host/virt_phy/src/virt_prim_pdch.c
new file mode 100644
index 00000000..3fa7977b
--- /dev/null
+++ b/src/host/virt_phy/src/virt_prim_pdch.c
@@ -0,0 +1,108 @@
+/*
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/gsm0502.h>
+
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/virtphy/logging.h>
+
+#include <osmocom/bb/l1ctl_proto.h>
+#include <osmocom/bb/l1gprs.h>
+
+void l1ctl_rx_gprs_uldl_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg)
+{
+ const struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
+
+ if (OSMO_UNLIKELY(ms->gprs == NULL)) {
+ LOGPMS(DL1C, LOGL_ERROR, ms, "l1gprs is not initialized\n");
+ return;
+ }
+
+ msg->l1h = msgb_pull(msg, sizeof(*l1h));
+
+ if (l1h->msg_type == L1CTL_GPRS_UL_TBF_CFG_REQ)
+ l1gprs_handle_ul_tbf_cfg_req(ms->gprs, msg);
+ else
+ l1gprs_handle_dl_tbf_cfg_req(ms->gprs, msg);
+}
+
+void l1ctl_rx_gprs_ul_block_req(struct l1_model_ms *ms, struct msgb *msg)
+{
+ const struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
+ struct l1gprs_prim_ul_block_req req;
+
+ if (OSMO_UNLIKELY(ms->gprs == NULL)) {
+ LOGPMS(DL1P, LOGL_ERROR, ms, "l1gprs is not initialized\n");
+ msgb_free(msg);
+ return;
+ }
+
+ msg->l1h = (void *)l1h->data;
+ if (l1gprs_handle_ul_block_req(ms->gprs, &req, msg) != 0) {
+ msgb_free(msg);
+ return;
+ }
+ msg->l2h = (void *)&req.data[0];
+
+ virt_l1_sched_schedule(ms, msg, req.hdr.fn, req.hdr.tn,
+ &gsmtapl1_tx_to_virt_um_inst);
+}
+
+void l1ctl_tx_gprs_dl_block_ind(struct l1_model_ms *ms, const struct msgb *msg,
+ uint32_t fn, uint8_t tn, uint8_t rxlev)
+{
+ struct l1gprs_prim_dl_block_ind ind;
+ struct msgb *nmsg;
+ uint8_t usf = 0xff;
+
+ if (ms->gprs == NULL)
+ return;
+
+ ind = (struct l1gprs_prim_dl_block_ind) {
+ .hdr = {
+ .fn = fn,
+ .tn = tn,
+ },
+ .meas = {
+ .ber10k = 0, /* perfect Um, no errors */
+ .ci_cb = 180, /* 18 dB */
+ .rx_lev = rxlev,
+ },
+ .data = msgb_data(msg),
+ .data_len = msgb_length(msg),
+ };
+
+ nmsg = l1gprs_handle_dl_block_ind(ms->gprs, &ind, &usf);
+ if (nmsg != NULL)
+ l1ctl_sap_tx_to_l23_inst(ms, nmsg);
+ /* Every fn % 13 == 12 we have either a PTCCH or an IDLE slot, thus
+ * every fn % 13 == 8 we add 5 frames, or 4 frames othrwise. The
+ * resulting value is first fn of the next block. */
+ const uint32_t rts_fn = GSM_TDMA_FN_SUM(fn, (fn % 13 == 8) ? 5 : 4);
+ nmsg = l1gprs_handle_rts_ind(ms->gprs, rts_fn, tn, usf);
+ if (nmsg != NULL)
+ l1ctl_sap_tx_to_l23_inst(ms, nmsg);
+}
diff --git a/src/host/virt_phy/src/virt_prim_pm.c b/src/host/virt_phy/src/virt_prim_pm.c
index 46370138..5883bbbe 100644
--- a/src/host/virt_phy/src/virt_prim_pm.c
+++ b/src/host/virt_phy/src/virt_prim_pm.c
@@ -15,10 +15,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -26,14 +22,15 @@
#include <string.h>
#include <stdlib.h>
-#include <osmocom/gsm/gsm_utils.h>
-#include <osmocom/gsm/protocol/gsm_08_58.h>
#include <osmocom/core/msgb.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/virt_l1_sched.h>
#include <osmocom/core/gsmtap.h>
-#include <virtphy/logging.h>
-#include <l1ctl_proto.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/l1ctl_proto.h>
/**
* @brief Change the signal strength for a given arfcn.
@@ -84,38 +81,49 @@ void l1ctl_rx_pm_req(struct l1_model_ms *ms, struct msgb *msg)
struct l1_state_ms *l1s = &ms->state;
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
struct l1ctl_pm_req *pm_req = (struct l1ctl_pm_req *) l1h->data;
- struct msgb *resp_msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
- uint16_t arfcn_next;
- /* convert to host order */
- pm_req->range.band_arfcn_from = ntohs(pm_req->range.band_arfcn_from);
- pm_req->range.band_arfcn_to = ntohs(pm_req->range.band_arfcn_to);
+ /* just parse the data from the request here */
+ l1s->pm.req.band_arfcn_from = ntohs(pm_req->range.band_arfcn_from);
+ l1s->pm.req.band_arfcn_to = ntohs(pm_req->range.band_arfcn_to);
- LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_PM_REQ TYPE=%u, FROM=%d, TO=%d\n",
- pm_req->type, pm_req->range.band_arfcn_from, pm_req->range.band_arfcn_to);
+ LOGPMS(DL1C, LOGL_DEBUG, ms, "Rx L1CTL_PM_REQ TYPE=%u, FROM=%d, TO=%d\n",
+ pm_req->type, l1s->pm.req.band_arfcn_from, l1s->pm.req.band_arfcn_to);
+
+ /* generating the response will happen delayed in a timer, as otherwise
+ * we will respond too fast, and 'mobile' will run havoc in a busy loop issuing
+ * endless PM_REQ until a cell eventually isfound */
+ osmo_timer_schedule(&l1s->pm.req.timer, 0, 300000);
+}
+
+static void pm_conf_timer_cb(void *data)
+{
+ struct l1_model_ms *ms = data;
+ struct l1_state_ms *l1s = &ms->state;
+ struct msgb *resp_msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
+ uint16_t arfcn_next;
- for (arfcn_next = pm_req->range.band_arfcn_from;
- arfcn_next <= pm_req->range.band_arfcn_to; ++arfcn_next) {
+ for (arfcn_next = l1s->pm.req.band_arfcn_from;
+ arfcn_next <= l1s->pm.req.band_arfcn_to; ++arfcn_next) {
struct l1ctl_pm_conf *pm_conf = (struct l1ctl_pm_conf *) msgb_put(resp_msg, sizeof(*pm_conf));
pm_conf->band_arfcn = htons(arfcn_next);
/* set min and max to the value calculated for that
* arfcn (IGNORE UPLINKK AND PCS AND OTHER FLAGS) */
pm_conf->pm[0] = dbm2rxlev(l1s->pm.meas.arfcn_sig_lev_dbm[arfcn_next & ARFCN_NO_FLAGS_MASK]);
pm_conf->pm[1] = dbm2rxlev(l1s->pm.meas.arfcn_sig_lev_dbm[arfcn_next & ARFCN_NO_FLAGS_MASK]);
- if (arfcn_next == pm_req->range.band_arfcn_to) {
+ if (arfcn_next == l1s->pm.req.band_arfcn_to) {
struct l1ctl_hdr *resp_l1h = msgb_l1(resp_msg);
resp_l1h->flags |= L1CTL_F_DONE;
}
- /* no more space to hold mor pm info in msgb, flush to l23 */
+ /* no more space to hold more pm info in msgb, flush to l23 */
if (msgb_tailroom(resp_msg) < sizeof(*pm_conf)) {
- LOGPMS(DL1C, LOGL_INFO, ms, "Tx L1CTL_PM_CONF\n");
+ LOGPMS(DL1C, LOGL_DEBUG, ms, "Tx L1CTL_PM_CONF\n");
l1ctl_sap_tx_to_l23_inst(ms, resp_msg);
resp_msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
}
}
/* transmit the remaining part of pm response to l23 */
if (resp_msg) {
- LOGPMS(DL1C, LOGL_INFO, ms, "Tx L1CTL_PM_CONF\n");
+ LOGPMS(DL1C, LOGL_DEBUG, ms, "Tx L1CTL_PM_CONF\n");
l1ctl_sap_tx_to_l23_inst(ms, resp_msg);
}
}
@@ -137,6 +145,7 @@ void prim_pm_init(struct l1_model_ms *model)
l1s->pm.meas.arfcn_sig_lev_timers[i].cb = prim_pm_timer_cb;
l1s->pm.meas.arfcn_sig_lev_timers[i].data = &l1s->pm.meas.arfcn_sig_lev_dbm[i];
}
+ osmo_timer_setup(&l1s->pm.req.timer, pm_conf_timer_cb, model);
}
void prim_pm_exit(struct l1_model_ms *model)
@@ -146,4 +155,5 @@ void prim_pm_exit(struct l1_model_ms *model)
for (i = 0; i < 1024; ++i)
osmo_timer_del(&l1s->pm.meas.arfcn_sig_lev_timers[i]);
+ osmo_timer_del(&l1s->pm.req.timer);
}
diff --git a/src/host/virt_phy/src/virt_prim_rach.c b/src/host/virt_phy/src/virt_prim_rach.c
index 94076cf9..d12e63c6 100644
--- a/src/host/virt_phy/src/virt_prim_rach.c
+++ b/src/host/virt_phy/src/virt_prim_rach.c
@@ -16,10 +16,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -27,16 +23,17 @@
#include <string.h>
#include <stdlib.h>
+#include <osmocom/core/msgb.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/gsm0502.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
-#include <osmocom/core/msgb.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/virt_l1_sched.h>
-#include <virtphy/logging.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <l1ctl_proto.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/l1ctl_proto.h>
/* use if we have a combined uplink (RACH, SDCCH, ...) (see
* http://www.rfwireless-world.com/Terminology/GSM-combined-channel-configuration.html)
@@ -79,36 +76,37 @@ void l1ctl_rx_rach_req(struct l1_model_ms *ms, struct msgb *msg)
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data;
struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *) ul->payload;
uint32_t fn_sched;
- uint8_t ts = 1; /* FIXME mostly, ts 1 is used for rach, where can i get that info? System info? */
uint16_t offset = ntohs(rach_req->offset);
LOGPMS(DL1C, LOGL_INFO, ms, "Rx L1CTL_RACH_REQ (ra=0x%02x, offset=%d combined=%d)\n",
rach_req->ra, offset, rach_req->combined);
- if (rach_req->ra == 0x03)
- fn_sched = 42;
-
/* set ra data to msg (8bits, the 11bit option is not used for GSM) */
msg->l2h = msgb_put(msg, sizeof(uint8_t));
*msg->l2h = rach_req->ra;
- /* chan_nr need to be encoded here, as it is not set by l23 for
- * the rach request, but needed by virt um */
- ul->chan_nr = rsl_enc_chan_nr(RSL_CHAN_RACH, 0, ts);
- ul->link_id = LID_DEDIC;
+ /* use the indicated RSL chan_nr/link_id, if provided */
+ if (ul->chan_nr == 0x00) {
+ LOGPMS(DL1C, LOGL_NOTICE, ms,
+ "The UL info header is empty, assuming RACH is on TS0\n");
+ ul->chan_nr = RSL_CHAN_RACH;
+ ul->link_id = LID_DEDIC;
+ }
/* sched fn calculation if we have a combined ccch channel configuration */
if (rach_req->combined) {
/* add elapsed RACH slots to offset */
offset += t3_to_rach_comb[l1s->current_time.t3];
/* offset is the number of RACH slots in the future */
- fn_sched = l1s->current_time.fn - l1s->current_time.t3;
+ fn_sched = GSM_TDMA_FN_SUB(l1s->current_time.fn, l1s->current_time.t3);
fn_sched += offset / 27 * 51;
fn_sched += rach_to_t3_comb[offset % 27];
+ fn_sched %= GSM_TDMA_HYPERFRAME;
} else
- fn_sched = l1s->current_time.fn + offset;
+ fn_sched = GSM_TDMA_FN_SUM(l1s->current_time.fn, offset);
- virt_l1_sched_schedule(ms, msg, fn_sched, ts, &virt_l1_sched_handler_cb);
+ virt_l1_sched_schedule(ms, msg, fn_sched, ul->chan_nr & 0x07,
+ &virt_l1_sched_handler_cb);
}
/**
diff --git a/src/host/virt_phy/src/virt_prim_traffic.c b/src/host/virt_phy/src/virt_prim_traffic.c
index 5f6b273b..778d67a3 100644
--- a/src/host/virt_phy/src/virt_prim_traffic.c
+++ b/src/host/virt_phy/src/virt_prim_traffic.c
@@ -16,10 +16,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -27,16 +23,16 @@
#include <string.h>
#include <stdlib.h>
+#include <osmocom/core/msgb.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
-#include <osmocom/core/msgb.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/virt_l1_sched.h>
-#include <virtphy/logging.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <l1ctl_proto.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/l1ctl_proto.h>
/**
* @brief Handler callback function for TRAFFIC request.
@@ -47,7 +43,8 @@
static void virt_l1_sched_handler_cb(struct l1_model_ms *ms, uint32_t fn, uint8_t tn, struct msgb * msg)
{
gsmtapl1_tx_to_virt_um_inst(ms, fn, tn, msg);
- l1ctl_tx_traffic_conf(ms, fn, 0, ms->state.serving_cell.arfcn);
+ /* FIXME: get ARFCN from msg payload */
+ l1ctl_tx_traffic_conf(ms, fn, 0, ms->state.dedicated.band_arfcn);
}
/**
@@ -78,13 +75,14 @@ void l1ctl_rx_traffic_req(struct l1_model_ms *ms, struct msgb *msg)
}
void l1ctl_tx_traffic_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arfcn, uint8_t link_id,
- uint8_t chan_nr, uint32_t fn, uint8_t snr, uint8_t signal_dbm,
+ uint8_t chan_nr, uint32_t fn, uint8_t snr, uint8_t rxlev,
uint8_t num_biterr, uint8_t fire_crc)
{
struct msgb *l1ctl_msg = NULL;
struct l1ctl_traffic_ind * l1ti;
struct l1ctl_info_dl * l1dl;
- uint8_t *frame, frame_len;
+ uint8_t *frame;
+ int frame_len;
uint8_t rsl_chan_type, subchan, timeslot;
l1ctl_msg = l1ctl_msgb_alloc(L1CTL_TRAFFIC_IND);
l1dl = (struct l1ctl_info_dl *) msgb_put(l1ctl_msg, sizeof(*l1dl));
@@ -97,15 +95,20 @@ void l1ctl_tx_traffic_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arf
l1dl->chan_nr = chan_nr;
l1dl->frame_nr = htonl(fn);
l1dl->snr = snr;
- l1dl->rx_level = signal_dbm;
+ l1dl->rx_level = rxlev;
l1dl->num_biterr = 0; /* no biterrors */
l1dl->fire_crc = 0;
- /* TODO: traffic decoding and decryption */
-
- frame_len = msgb_length(msg);
+ /* The first byte indicates the type of voice frame (enum gsmtap_um_voice_type),
+ * which we simply ignore here and pass on the frame without that byte.
+ * TODO: Check for consistency with ms->state.tch_mode ? */
+ frame_len = msgb_length(msg) - 1;
+ if (frame_len < 0) {
+ msgb_free(l1ctl_msg);
+ return;
+ }
frame = (uint8_t *) msgb_put(l1ctl_msg, frame_len);
- memcpy(frame, msgb_data(msg), frame_len);
+ memcpy(frame, msgb_data(msg)+1, frame_len);
DEBUGPMS(DL1P, ms, "Tx L1CTL_TRAFFIC_IND (chan_nr=0x%02x, link_id=0x%02x)\n", chan_nr, link_id);
l1ctl_sap_tx_to_l23_inst(ms, l1ctl_msg);
diff --git a/src/host/virt_phy/src/virtphy.c b/src/host/virt_phy/src/virtphy.c
index d0a2ddbf..0aa21adc 100644
--- a/src/host/virt_phy/src/virtphy.c
+++ b/src/host/virt_phy/src/virtphy.c
@@ -20,10 +20,6 @@
*
*/
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/gsmtap.h>
-#include <osmocom/core/application.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
@@ -31,15 +27,22 @@
#include <getopt.h>
#include <errno.h>
#include <signal.h>
-#include <virtphy/virtual_um.h>
-#include <virtphy/l1ctl_sock.h>
-#include <virtphy/virt_l1_model.h>
-#include <virtphy/l1ctl_sap.h>
-#include <virtphy/gsmtapl1_if.h>
-#include <virtphy/logging.h>
-#include <virtphy/virt_l1_sched.h>
-#define DEFAULT_LOG_MASK "DL1C,2:DL1P,2:DVIRPHY,2:DMAIN,1"
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/core/application.h>
+
+#include <osmocom/bb/virtphy/virtual_um.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/l1ctl_sap.h>
+#include <osmocom/bb/virtphy/gsmtapl1_if.h>
+#include <osmocom/bb/virtphy/logging.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+#include <osmocom/bb/l1gprs.h>
+
+#define DEFAULT_LOG_MASK "DL1C,2:DL1P,2:DVIRPHY,2:DGPRS,1:DMAIN,1"
/* this exists once in the program, and contains the state that we
* only keep once: L1CTL server socket, GSMTAP/VirtUM socket */
@@ -59,13 +62,15 @@ static char *log_mask = DEFAULT_LOG_MASK;
static char *l1ctl_sock_path = L1CTL_SOCK_PATH;
static char *arfcn_sig_lev_red_mask = NULL;
static char *pm_timeout = NULL;
+static char *mcast_netdev = NULL;
+static int mcast_ttl = -1;
-static void print_usage()
+static void print_usage(void)
{
printf("Usage: virtphy\n");
}
-static void print_help()
+static void print_help(void)
{
printf(" Some useful help...\n");
printf(" -h --help This text.\n");
@@ -76,6 +81,8 @@ static void print_help()
printf(" -s --l1ctl-sock l1ctl socket path path.\n");
printf(" -r --arfcn-sig-lev-red reduce signal level (e.g. 666,12:888,43:176,22).\n");
printf(" -t --pm-timeout power management timeout.\n");
+ printf(" -T --mcast-ttl TTL set TTL of Virtual Um GSMTAP multicast frames\n");
+ printf(" -D --mcast-deav NETDEV bind to given network device for Virtual Um\n");
}
static void handle_options(int argc, char **argv)
@@ -91,9 +98,11 @@ static void handle_options(int argc, char **argv)
{"l1ctl-sock", required_argument, 0, 's'},
{"arfcn-sig-lev-red", required_argument, 0, 'r'},
{"pm-timeout", required_argument, 0, 't'},
+ {"mcast-ttl", required_argument, 0, 'T'},
+ {"mcast-dev", required_argument, 0, 'D'},
{0, 0, 0, 0},
};
- c = getopt_long(argc, argv, "hz:y:x:d:s:r:t:", long_options,
+ c = getopt_long(argc, argv, "hz:y:x:d:s:r:t:T:D:", long_options,
&option_index);
if (c == -1)
break;
@@ -124,6 +133,12 @@ static void handle_options(int argc, char **argv)
case 't':
pm_timeout = optarg;
break;
+ case 'T':
+ mcast_ttl = atoi(optarg);
+ break;
+ case 'D':
+ mcast_netdev = optarg;
+ break;
default:
break;
}
@@ -227,12 +242,13 @@ int main(int argc, char *argv[])
/* init loginfo */
handle_options(argc, argv);
- ms_log_init(log_mask);
+ ms_log_init(tall_vphy_ctx, log_mask);
+ l1gprs_logging_init(DGPRS);
LOGP(DVIRPHY, LOGL_INFO, "Virtual physical layer starting up...\n");
- g_vphy.virt_um = virt_um_init(tall_vphy_ctx, ul_tx_grp, port, dl_rx_grp, port,
- gsmtapl1_rx_from_virt_um_inst_cb);
+ g_vphy.virt_um = virt_um_init(tall_vphy_ctx, ul_tx_grp, port, dl_rx_grp, port, mcast_ttl,
+ mcast_netdev, gsmtapl1_rx_from_virt_um_inst_cb);
g_vphy.l1ctl_sock = l1ctl_sock_init(tall_vphy_ctx, l1ctl_sap_rx_from_l23_inst_cb,
l1ctl_accept_cb, l1ctl_close_cb, l1ctl_sock_path);