This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgHarald Welte has submitted this change and it was merged.
Change subject: VIRT_PHY: Improved l1ctl-to-l23 interface + gsmtap header parsing.
......................................................................
VIRT_PHY: Improved l1ctl-to-l23 interface + gsmtap header parsing.
Fixed mapping from gsmtap msg type to rsl msg type and vice versa.
Proper chan_nr decoding instead of usage of dummy values for timeslot /
link_id / subslot.
Implemented missing l23 rx handler routines.
Change-Id: Ibad741d112643c55091b8ba00164b05d728ae1a1
---
M src/host/virt_phy/src/gsmtapl1_if.c
M src/host/virt_phy/src/gsmtapl1_if.h
M src/host/virt_phy/src/l1ctl_sap.c
M src/host/virt_phy/src/l1ctl_sap.h
M src/host/virt_phy/src/virt_l1_model.h
M src/host/virt_phy/src/virtphy.c
M src/host/virt_phy/src/virtual_um.c
7 files changed, 433 insertions(+), 342 deletions(-)
Approvals:
Harald Welte: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/src/host/virt_phy/src/gsmtapl1_if.c b/src/host/virt_phy/src/gsmtapl1_if.c
index 53cc952..d46bb2f 100644
--- a/src/host/virt_phy/src/gsmtapl1_if.c
+++ b/src/host/virt_phy/src/gsmtapl1_if.c
@@ -91,25 +91,43 @@
/**
* 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, uint8_t tn, uint32_t fn, uint8_t gsmtap_chan, struct msgb *msg)
+void gsmtapl1_tx_to_virt_um_inst(struct virt_um_inst *vui, uint32_t fn,
+ struct msgb *msg)
{
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
- uint8_t ss = 0;
- 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;
+ struct gsmtap_hdr *gh;
+ struct msgb *outmsg; // msg to send with gsmtap header prepended
+ 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
+ uint8_t *data = msgb_l2(msg); // data to transmit (whole message without l1 header)
+ uint8_t data_len = msgb_l2len(msg); // length of data
- outmsg = gsmtap_makemsg(l1_model_ms->state->serving_cell.arfcn, ul->chan_nr, gsmtap_chan,
- ss, fn, 0, 0, data,
- data_len);
+ uint8_t rsl_chantype; // rsl chan type (8.58, 9.3.1)
+ uint8_t subslot; // multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51)
+ uint8_t timeslot; // tdma timeslot to send in (0-7)
+ uint8_t gsmtap_chan; // the gsmtap channel
+
+ rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, ×lot);
+ gsmtap_chan = chantype_rsl2gsmtap(rsl_chantype, ul->link_id);
+
+ outmsg = gsmtap_makemsg(arfcn, timeslot, gsmtap_chan, subslot, fn,
+ signal_dbm, snr, data, data_len);
if (outmsg) {
- struct gsmtap_hdr *gh = msgb_data(msg);
- virt_um_write_msg(l1_model_ms->vui, outmsg);
- DEBUGP(DVIRPHY,
- "Sending gsmtap msg to virt um - (arfcn=%u, type=%u, subtype=%u, timeslot=%u, subslot=%u)\n",
- gh->arfcn, gh->type, gh->sub_type, gh->timeslot,
- gh->sub_slot);
+ outmsg->l1h = msgb_data(outmsg);
+ gh = msgb_l1(outmsg);
+ if (virt_um_write_msg(l1_model_ms->vui, outmsg) == -1) {
+ LOGP(DVIRPHY, LOGL_ERROR,
+ "Gsmtap msg could not send to virt um - (arfcn=%u, type=%u, subtype=%u, timeslot=%u, subslot=%u)\n",
+ gh->arfcn, gh->type, gh->sub_type,
+ gh->timeslot, gh->sub_slot);
+ } else {
+ DEBUGP(DVIRPHY,
+ "Sending gsmtap msg to virt um - (arfcn=%u, type=%u, subtype=%u, timeslot=%u, subslot=%u)\n",
+ gh->arfcn, gh->type, gh->sub_type,
+ gh->timeslot, gh->sub_slot);
+ }
} else {
LOGP(DVIRPHY, LOGL_ERROR, "Gsmtap msg could not be created!\n");
}
@@ -119,29 +137,12 @@
}
/**
- * @see void gsmtapl1_tx_to_virt_um(struct virt_um_inst *vui, uint8_t tn, uint32_t fn, uint8_t gsmtap_chan, 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(uint8_t tn, uint32_t fn, uint8_t gsmtap_chan, 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, tn, fn, gsmtap_chan, msg);
+ gsmtapl1_tx_to_virt_um_inst(l1_model_ms->vui, fn, msg);
}
-
-/* This is the header as it is used by gsmtap peer virtual layer 1.
-struct gsmtap_hdr {
- guint8 version; // version, set to 0x01 currently
- guint8 hdr_len; // length in number of 32bit words
- guint8 type; // see GSMTAP_TYPE_*
- guint8 timeslot; // timeslot (0..7 on Um)
- guint16 arfcn; // ARFCN (frequency)
- gint8 signal_dbm; // signal level in dBm
- gint8 snr_db; // signal/noise ratio in dB
- guint32 frame_number; // GSM Frame Number (FN)
- guint8 sub_type; // Type of burst/channel, see above
- guint8 antenna_nr; // Antenna Number
- guint8 sub_slot; // sub-slot within timeslot
- guint8 res; // reserved for future use (RFU)
-}
- */
/**
* Receive a gsmtap message from the virt um.
@@ -149,81 +150,117 @@
void gsmtapl1_rx_from_virt_um_inst_cb(struct virt_um_inst *vui,
struct msgb *msg)
{
- if (msg) {
- // we assume we only receive msgs if we actually camp on a cell
- if (l1_model_ms->state->camping) {
- struct gsmtap_hdr *gh;
- struct l1ctl_info_dl *l1dl;
- struct msgb *l1ctl_msg = NULL;
- struct l1ctl_data_ind * l1di;
-
- msg->l1h = msgb_data(msg);
- msg->l2h = msgb_pull(msg, sizeof(*gh));
- gh = msgb_l1(msg);
-
- DEBUGP(DVIRPHY,
- "Receiving gsmtap msg from virt um - (arfcn=%u, framenumber=%u, type=%s, subtype=%s, timeslot=%u, subslot=%u)\n",
- ntohs(gh->arfcn), ntohl(gh->frame_number), get_value_string(gsmtap_types, gh->type), get_value_string(gsmtap_channels, gh->sub_type), gh->timeslot,
- gh->sub_slot);
-
- // compose the l1ctl message for layer 2
- switch (gh->sub_type) {
- case GSMTAP_CHANNEL_RACH:
- LOGP(DL1C, LOGL_NOTICE,
- "Ignoring gsmtap msg from virt um - channel type is uplink only!\n");
- break;
- case GSMTAP_CHANNEL_TCH_F:
- l1ctl_msg = l1ctl_msgb_alloc(L1CTL_TRAFFIC_IND);
- // TODO: implement channel handling
- break;
- case GSMTAP_CHANNEL_SDCCH:
- case GSMTAP_CHANNEL_SDCCH4:
- case GSMTAP_CHANNEL_SDCCH8:
- // TODO: we might need to implement own channel handling for standalone dedicated channels
- case GSMTAP_CHANNEL_AGCH:
- case GSMTAP_CHANNEL_PCH:
- case GSMTAP_CHANNEL_BCCH:
- l1ctl_msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
- l1dl = (struct l1ctl_info_dl *) msgb_put(l1ctl_msg, sizeof(struct l1ctl_info_dl));
- l1di = (struct l1ctl_data_ind *) msgb_put(l1ctl_msg, sizeof(struct l1ctl_data_ind));
-
- l1dl->band_arfcn = htons(ntohs(gh->arfcn));
- l1dl->link_id = gh->timeslot;
- // see GSM 8.58 -> 9.3.1 for channel number encoding
- l1dl->chan_nr = rsl_enc_chan_nr(chantype_gsmtap2rsl(gh->sub_type), gh->sub_slot, gh->timeslot);
- l1dl->frame_nr = htonl(ntohl(gh->frame_number));
- l1dl->snr = gh->snr_db;
- l1dl->rx_level = gh->signal_dbm;
- l1dl->num_biterr = 0;
- l1dl->fire_crc = 0;
-
- memcpy(l1di->data, msgb_data(msg), msgb_length(msg));
-
- break;
- case GSMTAP_CHANNEL_CCCH:
- case GSMTAP_CHANNEL_TCH_H:
- case GSMTAP_CHANNEL_PACCH:
- case GSMTAP_CHANNEL_PDCH:
- case GSMTAP_CHANNEL_PTCCH:
- case GSMTAP_CHANNEL_CBCH51:
- case GSMTAP_CHANNEL_CBCH52:
- LOGP(DL1C, LOGL_NOTICE,
- "Ignoring gsmtap msg from virt um - channel type not supported!\n");
- break;
- default:
- LOGP(DL1C, LOGL_NOTICE,
- "Ignoring gsmtap msg from virt um - channel type unknown.\n");
- break;
- }
-
- /* forward l1ctl message to l2 */
- if(l1ctl_msg) {
- l1ctl_sap_tx_to_l23(l1ctl_msg);
- }
- }
- // handle memory deallocation
- talloc_free(msg);
+ if (!msg) {
+ return;
}
+ // we assume we only receive msgs if we actually camp on a cell
+ if (!l1_model_ms->state->camping) {
+ talloc_free(msg);
+ return;
+ }
+
+ struct gsmtap_hdr *gh = msgb_l1(msg);
+ struct msgb *l1ctl_msg = NULL;
+ struct l1ctl_info_dl *l1dl;
+ uint32_t fn = ntohl(gh->frame_number); // frame number of the rcv msg
+ uint16_t arfcn = ntohs(gh->arfcn); // arfcn of the cell we currently camp on
+ uint8_t gsmtap_chantype = gh->sub_type; // gsmtap channel type
+ uint8_t signal_dbm = gh->signal_dbm; // signal strength, 63 is best
+ uint8_t snr = gh->snr_db; // signal noise ratio, 63 is best
+ uint8_t subslot = gh->sub_slot; // multiframe subslot to send msg in (tch -> 0-26, bcch/ccch -> 0-51)
+ uint8_t timeslot = gh->timeslot; // tdma timeslot to send in (0-7)
+ uint8_t rsl_chantype; // rsl chan type (8.58, 9.3.1)
+ uint8_t link_id; // rsl link id tells if this is an ssociated or dedicated link
+ uint8_t chan_nr; // encoded rsl channel type, timeslot and mf subslot
+
+ msg->l2h = msgb_pull(msg, sizeof(*gh));
+ chantype_gsmtap2rsl(gsmtap_chantype, &rsl_chantype, &link_id);
+ // see GSM 8.58 -> 9.3.1 for channel number encoding
+ chan_nr = rsl_enc_chan_nr(rsl_chantype, subslot, timeslot);
+
+ DEBUGP(DVIRPHY,
+ "Receiving gsmtap msg from virt um - (arfcn=%u, framenumber=%u, type=%s, subtype=%s, timeslot=%u, subslot=%u, rsl_chan_type=0x%2x, link_id=0x%2x, chan_nr=0x%2x)\n",
+ arfcn, fn, get_value_string(gsmtap_types, gh->type),
+ get_value_string(gsmtap_channels, gsmtap_chantype),
+ timeslot, subslot, rsl_chantype, link_id, chan_nr);
+
+ // switch case with removed acch flag
+ switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) {
+ case GSMTAP_CHANNEL_TCH_H:
+ case GSMTAP_CHANNEL_TCH_F:
+ struct l1ctl_traffic_ind * l1ti;
+ l1ctl_msg = l1ctl_msgb_alloc(L1CTL_TRAFFIC_IND);
+ l1dl = (struct l1ctl_info_dl *)msgb_put(l1ctl_msg,
+ sizeof(struct l1ctl_info_dl));
+ l1ti = (struct l1ctl_traffic_ind *)msgb_put(l1ctl_msg,
+ sizeof(struct l1ctl_traffic_ind));
+
+ l1dl->band_arfcn = htons(arfcn);
+ l1dl->link_id = link_id;
+ l1dl->chan_nr = chan_nr;
+ l1dl->frame_nr = htonl(fn);
+ l1dl->snr = snr;
+ l1dl->rx_level = signal_dbm;
+ l1dl->num_biterr = 0; // no biterrors
+ l1dl->fire_crc = 0;
+
+ // TODO: traffic decoding and decryption
+
+ memcpy(l1ti->data, msgb_data(msg), msgb_length(msg));
+ break;
+ case GSMTAP_CHANNEL_SDCCH4:
+ case GSMTAP_CHANNEL_SDCCH8:
+ // TODO: we might need to implement own channel handling for standalone dedicated channels
+ case GSMTAP_CHANNEL_AGCH:
+ case GSMTAP_CHANNEL_PCH:
+ case GSMTAP_CHANNEL_BCCH:
+ struct l1ctl_data_ind * l1di;
+ l1ctl_msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
+ l1dl = (struct l1ctl_info_dl *)msgb_put(l1ctl_msg,
+ sizeof(struct l1ctl_info_dl));
+ l1di = (struct l1ctl_data_ind *)msgb_put(l1ctl_msg,
+ sizeof(struct l1ctl_data_ind));
+
+ l1dl->band_arfcn = htons(arfcn);
+ l1dl->link_id = link_id;
+ l1dl->chan_nr = chan_nr;
+ l1dl->frame_nr = htonl(fn);
+ l1dl->snr = snr;
+ l1dl->rx_level = signal_dbm;
+ l1dl->num_biterr = 0; // no biterrors
+ l1dl->fire_crc = 0; // TODO: check if this means fire crc is not used or crc produced no error
+
+ // TODO: data decoding and decryption
+
+ memcpy(l1di->data, msgb_data(msg), msgb_length(msg));
+
+ break;
+ case GSMTAP_CHANNEL_RACH:
+ LOGP(DVIRPHY, LOGL_NOTICE,
+ "Ignoring gsmtap msg from virt um - channel type is uplink only!\n");
+ break;
+ case GSMTAP_CHANNEL_SDCCH:
+ case GSMTAP_CHANNEL_CCCH:
+ case GSMTAP_CHANNEL_PACCH:
+ case GSMTAP_CHANNEL_PDCH:
+ case GSMTAP_CHANNEL_PTCCH:
+ case GSMTAP_CHANNEL_CBCH51:
+ case GSMTAP_CHANNEL_CBCH52:
+ LOGP(DVIRPHY, LOGL_NOTICE,
+ "Ignoring gsmtap msg from virt um - channel type not supported!\n");
+ break;
+ default:
+ LOGP(DVIRPHY, LOGL_NOTICE,
+ "Ignoring gsmtap msg from virt um - channel type unknown.\n");
+ break;
+ }
+
+ /* forward l1ctl message to l2 */
+ if (l1ctl_msg) {
+ l1ctl_sap_tx_to_l23(l1ctl_msg);
+ }
+ // handle memory deallocation
+ talloc_free(msg);
}
/**
@@ -236,41 +273,77 @@
/*! \brief convert GSMTAP channel type to RSL channel number
* \param[in] gsmtap_chantype GSMTAP channel type
- * \returns RSL channel type
+ * \param[out] rsl_chantype rsl channel type
+ * \param[out] rsl_chantype rsl link id
+ *
+ * Mapping from gsmtap channel:
+ * GSMTAP_CHANNEL_UNKNOWN * 0x00
+ * GSMTAP_CHANNEL_BCCH * 0x01
+ * GSMTAP_CHANNEL_CCCH * 0x02
+ * GSMTAP_CHANNEL_RACH * 0x03
+ * GSMTAP_CHANNEL_AGCH * 0x04
+ * GSMTAP_CHANNEL_PCH * 0x05
+ * GSMTAP_CHANNEL_SDCCH * 0x06
+ * GSMTAP_CHANNEL_SDCCH4 * 0x07
+ * GSMTAP_CHANNEL_SDCCH8 * 0x08
+ * GSMTAP_CHANNEL_TCH_F * 0x09
+ * GSMTAP_CHANNEL_TCH_H * 0x0a
+ * GSMTAP_CHANNEL_PACCH * 0x0b
+ * GSMTAP_CHANNEL_CBCH52 * 0x0c
+ * GSMTAP_CHANNEL_PDCH * 0x0d
+ * GSMTAP_CHANNEL_PTCCH * 0x0e
+ * GSMTAP_CHANNEL_CBCH51 * 0x0f
+ * to rsl channel type:
+ * RSL_CHAN_NR_MASK * 0xf8
+ * RSL_CHAN_NR_1 * * 0x08
+ * RSL_CHAN_Bm_ACCHs * 0x08
+ * RSL_CHAN_Lm_ACCHs * 0x10
+ * RSL_CHAN_SDCCH4_ACCH * 0x20
+ * RSL_CHAN_SDCCH8_ACCH * 0x40
+ * RSL_CHAN_BCCH * * 0x80
+ * RSL_CHAN_RACH * * 0x88
+ * RSL_CHAN_PCH_AGCH * 0x90
+ * RSL_CHAN_OSMO_PDCH * 0xc0
+ * and logical channel link id:
+ * LID_SACCH * * 0x40
+ * LID_DEDIC * * 0x00
+ *
+ * TODO: move this to a library used by both ms and bts virt um
*/
-uint8_t chantype_gsmtap2rsl(uint8_t gsmtap_chantype)
+void chantype_gsmtap2rsl(uint8_t gsmtap_chantype, uint8_t *rsl_chantype,
+ uint8_t *link_id)
{
- // TODO: proper retval for unknown channel
- uint8_t ret = 0;
-
- switch (gsmtap_chantype) {
- case GSMTAP_CHANNEL_TCH_F:
- ret = RSL_CHAN_Bm_ACCHs;
+ // switch case with removed acch flag
+ switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) {
+ case GSMTAP_CHANNEL_TCH_F: // TCH/F, FACCH/F
+ *rsl_chantype = RSL_CHAN_Bm_ACCHs;
break;
- case GSMTAP_CHANNEL_TCH_H:
- ret = RSL_CHAN_Lm_ACCHs;
+ case GSMTAP_CHANNEL_TCH_H: // TCH/H, FACCH/H
+ *rsl_chantype = RSL_CHAN_Lm_ACCHs;
break;
- case GSMTAP_CHANNEL_SDCCH4:
- ret = RSL_CHAN_SDCCH4_ACCH;
+ case GSMTAP_CHANNEL_SDCCH4: // SDCCH/4
+ *rsl_chantype = RSL_CHAN_SDCCH4_ACCH;
break;
- case GSMTAP_CHANNEL_SDCCH8:
- ret = RSL_CHAN_SDCCH8_ACCH;
+ case GSMTAP_CHANNEL_SDCCH8: // SDCCH/8
+ *rsl_chantype = RSL_CHAN_SDCCH8_ACCH;
break;
- case GSMTAP_CHANNEL_BCCH:
- ret = RSL_CHAN_BCCH;
+ case GSMTAP_CHANNEL_BCCH: // BCCH
+ *rsl_chantype = RSL_CHAN_BCCH;
break;
- case GSMTAP_CHANNEL_RACH:
- ret = RSL_CHAN_RACH;
+ case GSMTAP_CHANNEL_RACH: // RACH
+ *rsl_chantype = RSL_CHAN_RACH;
break;
- case GSMTAP_CHANNEL_PCH:
- case GSMTAP_CHANNEL_AGCH:
- ret = RSL_CHAN_PCH_AGCH;
+ case GSMTAP_CHANNEL_PCH: // PCH
+ case GSMTAP_CHANNEL_AGCH: // AGCH
+ *rsl_chantype = RSL_CHAN_PCH_AGCH;
+ break;
+ case GSMTAP_CHANNEL_PDCH:
+ *rsl_chantype = GSMTAP_CHANNEL_PDCH;
break;
}
- // TODO: check how to handle this...
-// if (link_id & 0x40)
-// ret |= GSMTAP_CHANNEL_ACCH;
+ *link_id = gsmtap_chantype & GSMTAP_CHANNEL_ACCH ?
+ LID_SACCH :
+ LID_DEDIC;
- return ret;
}
diff --git a/src/host/virt_phy/src/gsmtapl1_if.h b/src/host/virt_phy/src/gsmtapl1_if.h
index 09d34f4..6311e07 100644
--- a/src/host/virt_phy/src/gsmtapl1_if.h
+++ b/src/host/virt_phy/src/gsmtapl1_if.h
@@ -8,11 +8,11 @@
#include "virt_l1_model.h"
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_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, uint8_t tn, uint32_t fn, uint8_t gsmtap_chan, struct msgb *msg);
-void gsmtapl1_tx_to_virt_um(uint8_t tn, uint32_t fn, uint8_t gsmtap_chan, struct msgb *msg);
-
-uint8_t chantype_gsmtap2rsl(uint8_t gsmtap_chantype);
+void gsmtapl1_tx_to_virt_um_inst(struct virt_um_inst *vui, uint32_t fn,
+ 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);
diff --git a/src/host/virt_phy/src/l1ctl_sap.c b/src/host/virt_phy/src/l1ctl_sap.c
index b5fb0f0..91f1d10 100644
--- a/src/host/virt_phy/src/l1ctl_sap.c
+++ b/src/host/virt_phy/src/l1ctl_sap.c
@@ -4,9 +4,13 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/gsmtap.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/rsl.h>
#include <stdio.h>
#include <l1ctl_proto.h>
#include <netinet/in.h>
+#include <string.h>
#include "virtual_um.h"
#include "l1ctl_sock.h"
@@ -16,6 +20,18 @@
#include "gsmtapl1_if.h"
static struct l1_model_ms *l1_model_ms = NULL;
+
+static void l1_model_tch_mode_set(uint8_t tch_mode)
+{
+ if (tch_mode == GSM48_CMODE_SPEECH_V1
+ || tch_mode == GSM48_CMODE_SPEECH_EFR) {
+ l1_model_ms->state->tch_mode = tch_mode;
+
+ } else {
+ // set default value if no proper mode was assigned by l23
+ l1_model_ms->state->tch_mode = GSM48_CMODE_SIGN;
+ }
+}
/**
* @brief Init the SAP.
@@ -30,7 +46,8 @@
*
* Enqueues the message into the rx queue.
*/
-void l1ctl_sap_rx_from_l23_inst_cb(struct l1ctl_sock_inst *lsi, struct msgb *msg)
+void l1ctl_sap_rx_from_l23_inst_cb(struct l1ctl_sock_inst *lsi,
+ struct msgb *msg)
{
// check if the received msg is not empty
if (msg) {
@@ -56,11 +73,11 @@
{
uint16_t *len;
/* prepend 16bit length before sending */
- len = (uint16_t *) msgb_push(msg, sizeof(*len));
+ len = (uint16_t *)msgb_push(msg, sizeof(*len));
*len = htons(msg->len - sizeof(*len));
- if(l1ctl_sock_write_msg(lsi, msg) == -1 ) {
- //DEBUGP(DL1C, "Error writing to layer2 socket");
+ if (l1ctl_sock_write_msg(lsi, msg) == -1) {
+ DEBUGP(DL1C, "Error writing to layer2 socket");
}
}
@@ -140,22 +157,22 @@
/**
* @brief General handler for incoming L1CTL messages from layer 2/3.
*
- * This handler will dequeue the rx queue (if !empty) and call the specific routine for the dequeued l1ctl message.
+ * This handler will call the specific routine dependent on the L1CTL message type.
*
*/
void l1ctl_sap_handler(struct msgb *msg)
{
-// struct msgb *msg;
struct l1ctl_hdr *l1h;
- unsigned long flags;
- if (!msg)
+ if (!msg) {
return;
+ }
l1h = (struct l1ctl_hdr *)msg->data;
if (sizeof(*l1h) > msg->len) {
- LOGP(DL1C, LOGL_NOTICE, "Short message. %u\n", msg->len);
+ LOGP(DL1C, LOGL_NOTICE, "Malformed message: too short. %u\n",
+ msg->len);
goto exit_msgbfree;
}
@@ -182,7 +199,6 @@
l1ctl_rx_rach_req(msg);
// msg is freed by rx routine
goto exit_nofree;
- break;
case L1CTL_DATA_REQ:
l1ctl_rx_data_req(msg);
/* we have to keep the msgb, not free it! */
@@ -229,24 +245,29 @@
* Transmit frequency control and synchronisation bursts on FCCH and SCH to calibrate transceiver and search for base stations.
* Sync to a given arfcn.
*
- * Note: Not needed for virtual physical layer.
+ * Note: ms will start receiving msgs on virtual um only after this req was received.
+ * Note: virt bts does not broadcast freq and sync bursts.
+ *
* TODO: Could be used to bind/connect to different virtual_bts sockets with a arfcn-socket mapping.
+ * TODO: Check flags if this is a sync or freq request and handle it accordingly.
*/
void l1ctl_rx_fbsb_req(struct msgb *msg)
{
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_fbsb_req *sync_req = (struct l1ctl_fbsb_req *)l1h->data;
- DEBUGP(DL1C, "Received and handled from l23 - L1CTL_FBSB_REQ (arfcn=%u, flags=0x%x)\n",
+ DEBUGP(DL1C,
+ "Received and handled from l23 - L1CTL_FBSB_REQ (arfcn=%u, flags=0x%x)\n",
ntohs(sync_req->band_arfcn), sync_req->flags);
l1_model_ms->state->camping = 1;
- l1_model_ms->state->serving_cell.arfcn = ntohs(sync_req->band_arfcn);
- l1_model_ms->state->serving_cell.ccch_mode = sync_req->ccch_mode;
- l1_model_ms->state->serving_cell.fn_offset = 0;
- l1_model_ms->state->serving_cell.bsic = 0;
- l1_model_ms->state->serving_cell.time_alignment = 0;
- // TODO: reset and synchronize the ms uplink schedulers with bts multiframe structure.
+ l1_model_ms->state->serving_cell.arfcn = ntohs(sync_req->band_arfcn); // freq req
+
+ // not needed in virt um
+ l1_model_ms->state->serving_cell.ccch_mode = sync_req->ccch_mode; // sync req
+ l1_model_ms->state->serving_cell.fn_offset = 0; // sync req
+ l1_model_ms->state->serving_cell.bsic = 0; // sync req
+ l1_model_ms->state->serving_cell.time_alignment = 0; // sync req
l1ctl_tx_fbsb_conf(0, l1_model_ms->state->serving_cell.arfcn);
}
@@ -268,47 +289,25 @@
struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
struct l1ctl_dm_est_req *est_req =
(struct l1ctl_dm_est_req *)ul->payload;
+ uint8_t rsl_chantype, subslot, timeslot;
+
+ rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, ×lot);
DEBUGP(DL1C,
- "Received and handled from l23 - L1CTL_DM_EST_REQ (arfcn=%u, chan_nr=0x%02x, tsc=%u)\n",
- ntohs(est_req->h0.band_arfcn), ul->chan_nr,
- est_req->tsc);
+ "Received and handled from l23 - L1CTL_DM_EST_REQ (chan_nr=0x%02x, tn=%u)\n",
+ ul->chan_nr, timeslot);
-// /* disable neighbour cell measurement of C0 TS 0 */
-// mframe_disable(MF_TASK_NEIGH_PM51_C0T0);
-//
-// /* configure dedicated channel state */
-// l1s.dedicated.type = chan_nr2dchan_type(ul->chan_nr);
-// l1s.dedicated.tsc = est_req->tsc;
-// l1s.dedicated.tn = ul->chan_nr & 0x7;
-// l1s.dedicated.h = est_req->h;
-//
-// if (est_req->h) {
-// int i;
-// l1s.dedicated.h1.hsn = est_req->h1.hsn;
-// l1s.dedicated.h1.maio = est_req->h1.maio;
-// l1s.dedicated.h1.n = est_req->h1.n;
-// for (i=0; i<est_req->h1.n; i++)
-// l1s.dedicated.h1.ma[i] = ntohs(est_req->h1.ma[i]);
-// } else {
-// l1s.dedicated.h0.arfcn = ntohs(est_req->h0.band_arfcn);
-// }
-//
-// /* TCH config */
-// if (chan_nr_is_tch(ul->chan_nr)) {
-// /* Mode */
-// l1a_tch_mode_set(est_req->tch_mode);
-// l1a_audio_mode_set(est_req->audio_mode);
-//
-// /* Sync */
-// l1s.tch_sync = 1; /* can be set without locking */
-//
-// /* Audio path */
-// audio_set_enabled(est_req->tch_mode, est_req->audio_mode);
-// }
-//
-// /* figure out which MF tasks to enable */
-// l1a_mftask_set(chan_nr2mf_task_mask(ul->chan_nr, NEIGH_MODE_PM));
+ l1_model_ms->state->dedicated.chan_type = rsl_chantype;
+ l1_model_ms->state->dedicated.tn = timeslot;
+
+ /* TCH config */
+ if (rsl_chantype == RSL_CHAN_Bm_ACCHs
+ || rsl_chantype == RSL_CHAN_Lm_ACCHs) {
+ l1_model_ms->state->tch_mode = est_req->tch_mode;
+ l1_model_tch_mode_set(est_req->tch_mode);
+ l1_model_ms->state->audio_mode = est_req->audio_mode;
+ // TODO: configure audio hardware for encoding / decoding / recording / playing voice
+ }
}
/**
@@ -320,7 +319,7 @@
*
* Handle frequency change in dedicated mode. E.g. used for frequency hopping.
*
- * Note: Not needed for virtual physical layer.
+ * Note: Not needed for virtual physical layer as freqency hopping is generally disabled.
*/
void l1ctl_rx_dm_freq_req(struct msgb *msg)
{
@@ -330,8 +329,9 @@
(struct l1ctl_dm_freq_req *)ul->payload;
DEBUGP(DL1C,
- "Received and ignored from l23 - L1CTL_DM_FREQ_REQ (arfcn=%u, tsc=%u)\n",
- ntohs(freq_req->h0.band_arfcn), freq_req->tsc);
+ "Received and ignored from l23 - L1CTL_DM_FREQ_REQ (arfcn0=%u, hsn=%u, maio=%u)\n",
+ ntohs(freq_req->h0.band_arfcn), freq_req->h1.hsn,
+ freq_req->h1.maio);
}
/**
@@ -359,12 +359,14 @@
"Received and handled from l23 - L1CTL_CRYPTO_REQ (algo=A5/%u, len=%u)\n",
cr->algo, key_len);
-// if (cr->algo && key_len != 8) {
-// DEBUGP(DL1C, "L1CTL_CRYPTO_REQ -> Invalid key\n");
-// return;
-// }
-//
-// dsp_load_ciph_param(cr->algo, cr->key);
+ if (cr->algo && key_len != A5_KEY_LEN) {
+ DEBUGP(DL1C, "L1CTL_CRYPTO_REQ -> Invalid key\n");
+ return;
+ }
+
+ l1_model_ms->crypto_inf->algo = cr->algo;
+ memcpy(l1_model_ms->crypto_inf->key, cr->key,
+ sizeof(uint8_t) * A5_KEY_LEN);
}
/**
@@ -380,19 +382,13 @@
*/
void l1ctl_rx_dm_rel_req(struct msgb *msg)
{
-// struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
+ DEBUGP(DL1C, "Received and handled from l23 - L1CTL_DM_REL_REQ\n");
- DEBUGP(DL1C, "Received and ignored from l23 - L1CTL_DM_REL_REQ\n");
-// l1a_mftask_set(0);
-// l1s.dedicated.type = GSM_DCHAN_NONE;
-// l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_MAIN]);
-// l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_SACCH]);
-// l1a_txq_msgb_flush(&l1s.tx_queue[L1S_CHAN_TRAFFIC]);
-// l1a_meas_msgb_set(NULL);
-// dsp_load_ciph_param(0, NULL);
-// l1a_tch_mode_set(GSM48_CMODE_SIGN);
-// audio_set_enabled(GSM48_CMODE_SIGN, 0);
-// l1s.neigh_pm.n = 0;
+ l1_model_ms->state->dedicated.chan_type = 0;
+ l1_model_ms->state->tch_mode = GSM48_CMODE_SIGN;
+
+ // TODO: disable ciphering
+ // TODO: disable audio recording / playing
}
/**
@@ -424,44 +420,38 @@
*
* @param [in] msg the received message.
*
- * Transmit RACH request on RACH.
+ * Transmit RACH request on RACH. Refer to 04.08 - 9.1.8 - Channel request.
*
- * TODO: Implement this handler routine!
*/
void l1ctl_rx_rach_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_rach_req *rach_req = (struct l1ctl_rach_req *) ul->payload;
-
- uint32_t fn_sched;
- uint8_t ts;
+ struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
+ struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *)l1h->data;
+ struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *)ul->payload;
+ // FIXME: proper frame number
+ uint32_t fn_sched = 42;
DEBUGP(DL1C,
"Received and handled from l23 - L1CTL_RACH_REQ (ra=0x%02x, offset=%d combined=%d)\n",
rach_req->ra, ntohs(rach_req->offset),
rach_req->combined);
- // TODO: calculate correct fn/ts for a RACH (if needed by bts)
- // TODO: implement scheduler for uplink!
- fn_sched = 42;
- ts = 0;
// for the rach channel request, there is no layer2 header, but only the one bit ra content to submit
- // see 4.18-9.1.8 CHannel Request
- // that means we have to set l2h of msgb to the ra content
- msg->l2h = &rach_req->ra;
- // avoid all data after ra to also be submitted
- msgb_trim(msg, sizeof(rach_req->ra));
- // TODO: check if we need to submit more data than the ra content to the bts
+ // replace l1ctl_rach_req with ra data that rly shall be submitted
+ // ra on peer side is decoded as uint16_t, but we do not use the 11bit option and thus 8bits must be sufficient
+ msg->l2h = msgb_put(msg, sizeof(uint8_t));
+ *msg->l2h = rach_req->ra;
+
+ // chan_nr is not specified in info_ul for rach request coming from l23, but needed in gsmtapl1_tx_to_virt_um()
+ ul->chan_nr = rsl_enc_chan_nr(RSL_CHAN_RACH, 0, 0);
+ ul->link_id = LID_DEDIC;
// send rach over virt um
- gsmtapl1_tx_to_virt_um(ts, fn_sched, GSMTAP_CHANNEL_RACH, msg);
+ gsmtapl1_tx_to_virt_um(fn_sched, msg);
// send confirm to layer23
l1ctl_tx_rach_conf(fn_sched, l1_model_ms->state->serving_cell.arfcn);
-// l1a_rach_req(ntohs(rach_req->offset), rach_req->combined,
-// rach_req->ra);
}
/**
@@ -473,36 +463,29 @@
*
* Transmit message on a signalling channel. FACCH/SDCCH or SACCH depending on the headers set link id (TS 8.58 - 9.3.2).
*
- * TODO: Implement this handler routine!
+ * TODO: Check if a msg on FACCH is coming in here and 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;
- struct llist_head *tx_queue;
+ // FIXME: proper frame number
+ uint32_t fn_sched = 42;
DEBUGP(DL1C,
- "Received and handled from l23 - L1CTL_DATA_REQ (link_id=0x%02x)\n",
- ul->link_id);
+ "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->l3h = data_ind->data;
-// if (ul->link_id & 0x40) {
-// struct gsm48_hdr *gh = (struct gsm48_hdr *)(data_ind->data + 5);
-// if (gh->proto_discr == GSM48_PDISC_RR
-// && gh->msg_type == GSM48_MT_RR_MEAS_REP) {
-// DEBUGP(DL1C, "updating measurement report\n");
-// l1a_meas_msgb_set(msg);
-// return;
-// }
-// tx_queue = &l1s.tx_queue[L1S_CHAN_SACCH];
-// } else
-// tx_queue = &l1s.tx_queue[L1S_CHAN_MAIN];
-//
-// DEBUGP(DL1C, "ul=%p, ul->payload=%p, data_ind=%p, data_ind->data=%p l3h=%p\n",
-// ul, ul->payload, data_ind, data_ind->data, msg->l3h);
-//
-// l1a_txq_msgb_enq(tx_queue, msg);
+ msg->l2h = data_ind->data;
+
+ // send msg over virt um
+ gsmtapl1_tx_to_virt_um(fn_sched, msg);
+
+ // send confirm to layer23
+ msg = l1ctl_create_l2_msg(L1CTL_DATA_CONF, fn_sched, 0, 0);
+ l1ctl_sap_tx_to_l23(msg);
}
/**
@@ -528,26 +511,33 @@
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);
- DEBUGP(DL1C, "Received from l23 - 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);
+ DEBUGP(DL1C,
+ "Received from l23 - 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);
- for(arfcn_next = pm_req->range.band_arfcn_from; arfcn_next <= pm_req->range.band_arfcn_to; ++arfcn_next) {
- struct l1ctl_pm_conf *pm_conf = (struct l1ctl_pm_conf *)msgb_put(resp_msg, sizeof(*pm_conf));
+ for (arfcn_next = pm_req->range.band_arfcn_from;
+ arfcn_next <= pm_req->range.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);
// rxlev 63 is great, 0 is bad the two values are min and max
pm_conf->pm[0] = 63;
pm_conf->pm[1] = 63;
- if(arfcn_next == pm_req->range.band_arfcn_to) {
+ if (arfcn_next == pm_req->range.band_arfcn_to) {
struct l1ctl_hdr *resp_l1h = msgb_l1(resp_msg);
resp_l1h->flags |= L1CTL_F_DONE;
}
- // no more space in msgb, flush to l2
- if(msgb_tailroom(resp_msg) < sizeof(*pm_conf)) {
+ // no more space to hold mor pm info in msgb, flush to l23
+ if (msgb_tailroom(resp_msg) < sizeof(*pm_conf)) {
l1ctl_sap_tx_to_l23(resp_msg);
resp_msg = l1ctl_msgb_alloc(L1CTL_PM_CONF);
}
}
- if(resp_msg) {
+ // transmit the remaining part of pm response to l23
+ if (resp_msg) {
l1ctl_sap_tx_to_l23(resp_msg);
}
}
@@ -563,7 +553,6 @@
*
* Note: Currently we do not perform anything else than response with a reset confirm
* to just tell l2 that we are rdy.
- * TODO: Validate if an action has to be done here.
*
*/
void l1ctl_rx_reset_req(struct msgb *msg)
@@ -573,16 +562,20 @@
switch (reset_req->type) {
case L1CTL_RES_T_FULL:
- DEBUGP(DL1C, "Received and handled from l23 - L1CTL_RESET_REQ (type=FULL)\n");
+ DEBUGP(DL1C,
+ "Received and handled from l23 - L1CTL_RESET_REQ (type=FULL)\n");
l1_model_ms->state->camping = 0;
+ // TODO: check if we also need to reset the dedicated channel state
l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
break;
case L1CTL_RES_T_SCHED:
- DEBUGP(DL1C, "Received and handled from l23 - L1CTL_RESET_REQ (type=SCHED)\n");
+ DEBUGP(DL1C,
+ "Received and handled from l23 - L1CTL_RESET_REQ (type=SCHED)\n");
l1ctl_tx_reset(L1CTL_RESET_CONF, reset_req->type);
break;
default:
- LOGP(DL1C, LOGL_ERROR, "Received and ignored from l23 - L1CTL_RESET_REQ (type=unknown)\n");
+ LOGP(DL1C, LOGL_ERROR,
+ "Received and ignored from l23 - L1CTL_RESET_REQ (type=unknown)\n");
break;
}
}
@@ -595,6 +588,8 @@
* @param [in] msg the received message.
*
* Configure CCCH combined / non-combined mode.
+ *
+ * @see l1ctl_proto.h -- enum ccch_mode
*
* TODO: Implement this handler routine!
*/
@@ -610,22 +605,7 @@
l1_model_ms->state->serving_cell.ccch_mode = ccch_mode;
// check if more has to be done here
-
l1ctl_tx_ccch_mode_conf(ccch_mode);
-
-// /* pre-set the CCCH mode */
-// l1s.serving_cell.ccch_mode = ccch_mode;
-//
-// /* Update task */
-// mframe_disable(MF_TASK_CCCH_COMB);
-// mframe_disable(MF_TASK_CCCH);
-//
-// if (ccch_mode == CCCH_MODE_COMBINED)
-// mframe_enable(MF_TASK_CCCH_COMB);
-// else if (ccch_mode == CCCH_MODE_NON_COMBINED)
-// mframe_enable(MF_TASK_CCCH);
-//
-// l1ctl_tx_ccch_mode_conf(ccch_mode);
}
/**
@@ -644,20 +624,18 @@
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *)msg->data;
struct l1ctl_tch_mode_req *tch_mode_req =
(struct l1ctl_tch_mode_req *)l1h->data;
- uint8_t tch_mode = tch_mode_req->tch_mode;
- uint8_t audio_mode = tch_mode_req->audio_mode;
+
+ l1_model_tch_mode_set(tch_mode_req->tch_mode);
+ l1_model_ms->state->audio_mode = tch_mode_req->audio_mode;
DEBUGP(DL1C,
"Received and handled from l23 - L1CTL_TCH_MODE_REQ (tch_mode=0x%02x audio_mode=0x%02x)\n",
- tch_mode, audio_mode);
-// tch_mode = l1a_tch_mode_set(tch_mode);
-// audio_mode = l1a_audio_mode_set(audio_mode);
-//
-// audio_set_enabled(tch_mode, audio_mode);
-//
-// l1s.tch_sync = 1; /* Needed for audio to work */
-//
-// l1ctl_tx_tch_mode_conf(tch_mode, audio_mode);
+ tch_mode_req->tch_mode, tch_mode_req->audio_mode);
+
+ // TODO: configure audio hardware for encoding / decoding / recording / playing voice
+
+ l1ctl_tx_tch_mode_conf(l1_model_ms->state->tch_mode,
+ l1_model_ms->state->audio_mode);
}
/**
@@ -671,7 +649,7 @@
* 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.
+ * Note: Not needed for virtual physical layer as we dont maintain neigbors.
*/
void l1ctl_rx_neigh_pm_req(struct msgb *msg)
{
@@ -691,30 +669,26 @@
*
* @param [in] msg the received message.
*
- * Enqueue the message (traffic frame) to the L1 state machine's transmit queue.
- * Will drop the traffic frame at queue sizes >= 4.
+ * Enqueue the message (traffic frame) to the L1 state machine's transmit queue. In virtual layer1 just submit it to the virt um.
*
- * TODO: Implement this handler routine!
*/
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;
- int num = 0;
+ uint32_t fn_sched = 42;
DEBUGP(DL1C, "Received and handled from l23 - L1CTL_TRAFFIC_REQ\n");
-// msg->l2h = tr->data;
+ msg->l2h = tr->data;
-// num = l1a_txq_msgb_count(&l1s.tx_queue[L1S_CHAN_TRAFFIC]);
-// if (num >= 4) {
-// DEBUGP(DL1C, "dropping traffic frame\n");
-// msgb_free(msg);
-// return;
-// }
-//
-// l1a_txq_msgb_enq(&l1s.tx_queue[L1S_CHAN_TRAFFIC], msg);
+ // send msg over virt um
+ gsmtapl1_tx_to_virt_um(fn_sched, msg);
+
+ // send confirm to layer23
+ msg = l1ctl_create_l2_msg(L1CTL_TRAFFIC_CONF, fn_sched, 0, 0);
+ l1ctl_sap_tx_to_l23(msg);
}
/**
@@ -727,6 +701,7 @@
* Forward and a sim request to the SIM APDU.
*
* Note: Not needed for virtual layer. Please configure layer23 application to use test-sim implementation.
+ * In this case layer1 wont need to handle sim logic.
* ms <x>
* --------
* sim test
@@ -766,7 +741,7 @@
reset_resp->type = reset_type;
DEBUGP(DL1C, "Sending to l23 - %s (reset_type: %u)\n",
- getL1ctlPrimName(msg_type), reset_type);
+ getL1ctlPrimName(msg_type), reset_type);
l1ctl_sap_tx_to_l23(msg);
}
@@ -783,7 +758,7 @@
struct msgb * msg = l1ctl_create_l2_msg(L1CTL_RACH_CONF, fn, 0, arfcn);
DEBUGP(DL1C, "Sending to l23 - %s (fn: %u, arfcn: %u)\n",
- getL1ctlPrimName(L1CTL_RACH_CONF), fn, arfcn);
+ getL1ctlPrimName(L1CTL_RACH_CONF), fn, arfcn);
l1ctl_sap_tx_to_l23(msg);
}
@@ -807,22 +782,20 @@
* @param [in] res 0 -> success, 255 -> error.
* @param [in] arfcn the arfcn we are synced to.
*
- * No calculation needed for virtual pyh -> uses default values for a good link quality.
+ * No calculation needed for virtual pyh -> uses dummy values for a good link quality.
*/
void l1ctl_tx_fbsb_conf(uint8_t res, uint16_t arfcn)
{
struct msgb *msg;
struct l1ctl_fbsb_conf *resp;
uint32_t fn = 0; // 0 should be okay here
- uint16_t snr = 40; // signal noise ratio > 40db is best signal.
- int16_t initial_freq_err = 0; // 0 means no error.
- uint8_t bsic = 0;
+ uint16_t snr = 40; // signal noise ratio > 40db is best signal (unused in virt)
+ int16_t initial_freq_err = 0; // 0 means no error (unused in virt)
+ uint8_t bsic = 0; // bsci can be read from sync burst (unused in virt)
- msg = l1ctl_create_l2_msg(L1CTL_FBSB_CONF, fn,
- snr,
- arfcn);
+ msg = l1ctl_create_l2_msg(L1CTL_FBSB_CONF, fn, snr, arfcn);
- resp = (struct l1ctl_fbsb_conf *) msgb_put(msg, sizeof(*resp));
+ resp = (struct l1ctl_fbsb_conf *)msgb_put(msg, sizeof(*resp));
resp->initial_freq_err = htons(initial_freq_err);
resp->result = res;
resp->bsic = bsic;
@@ -875,9 +848,8 @@
mode_conf->audio_mode = audio_mode;
DEBUGP(DL1C,
- "Sending to l23 - L1CTL_TCH_MODE_CONF (tch_mode: %u, audio_mode: %u)\n", tch_mode,
- audio_mode);
+ "Sending to l23 - L1CTL_TCH_MODE_CONF (tch_mode: %u, audio_mode: %u)\n",
+ tch_mode, audio_mode);
l1ctl_sap_tx_to_l23(msg);
}
-
diff --git a/src/host/virt_phy/src/l1ctl_sap.h b/src/host/virt_phy/src/l1ctl_sap.h
index f540197..9472013 100644
--- a/src/host/virt_phy/src/l1ctl_sap.h
+++ b/src/host/virt_phy/src/l1ctl_sap.h
@@ -15,6 +15,10 @@
#define L3_MSG_DATA 200
#define L3_MSG_SIZE (sizeof(struct l1ctl_hdr) + L3_MSG_HEAD + L3_MSG_DATA)
+/* lchan link ID */
+#define LID_SACCH 0x40
+#define LID_DEDIC 0x00
+
void l1ctl_sap_init(struct l1_model_ms *model);
void l1ctl_sap_tx_to_l23_inst(struct l1ctl_sock_inst *lsi, struct msgb *msg);
void l1ctl_sap_tx_to_l23(struct msgb *msg);
diff --git a/src/host/virt_phy/src/virt_l1_model.h b/src/host/virt_phy/src/virt_l1_model.h
index f0619ab..38d9efe 100644
--- a/src/host/virt_phy/src/virt_l1_model.h
+++ b/src/host/virt_phy/src/virt_l1_model.h
@@ -1,29 +1,65 @@
#pragma once
-#include <layer1/sync.h>
#include "l1ctl_sock.h"
#include "virtual_um.h"
+
+#define L1S_NUM_NEIGH_CELL 6
+#define A5_KEY_LEN 8
struct l1_model_ms {
struct l1ctl_sock_inst *lsi;
struct virt_um_inst *vui;
struct l1_state_ms *state;
+ struct crypto_info_ms *crypto_inf;
};
-//TODO: must contain logical channel information (fram number, ciphering mode, ...)
+/* structure representing L1 sync information about a cell */
+struct l1_cell_info {
+ /* on which ARFCN (+band) is the cell? */
+ uint16_t arfcn;
+ /* what's the BSIC of the cell (from SCH burst decoding) */
+ uint8_t bsic;
+ /* Combined or non-combined CCCH */
+ uint8_t ccch_mode; /* enum ccch_mode */
+ /* whats the delta of the cells current GSM frame number
+ * compared to our current local frame number */
+ int32_t fn_offset;
+ /* how much does the TPU need adjustment (delta) to synchronize
+ * with the cells burst */
+ uint32_t time_alignment;
+};
+
+struct crypto_info_ms {
+ /* key is expected in the same format as in RSL
+ * Encryption information IE. */
+ uint8_t key[A5_KEY_LEN];
+ uint8_t algo;
+};
+
struct l1_state_ms {
- uint8_t camping;
+ uint8_t camping; // are we currently camping on a cell
+
/* the cell on which we are camping right now */
struct l1_cell_info serving_cell;
-
/* neighbor cell sync info */
struct l1_cell_info neigh_cell[L1S_NUM_NEIGH_CELL];
- /* TCH */
- uint8_t tch_mode;
- uint8_t tch_sync;
- uint8_t audio_mode;
+ /* TCH info */
+ uint8_t tch_mode; // see enum gsm48_chan_mode in gsm_04_08.h
+ uint8_t tch_sync; // needed for audio synchronization
+ uint8_t audio_mode; // see l1ctl_proto.h, e.g. AUDIO_TX_MICROPHONE
+
+ /* dedicated channel info */
+ struct {
+ uint8_t chan_type; // like rsl chantype 08.58 -> Chapter 9.3.1 */
+
+ uint8_t tn; // timeslot number 1-7
+
+ uint8_t scn; // single-hop cellular network? (ununsed in virtual um)
+ uint8_t tsc; // training sequence code (ununsed in virtual um)
+ uint8_t h; // hopping enabled flag (ununsed in virtual um)
+ } dedicated;
};
struct l1_model_ms *l1_model_ms_init(void *ctx);
diff --git a/src/host/virt_phy/src/virtphy.c b/src/host/virt_phy/src/virtphy.c
index 94f6fa5..b2a2d4f 100644
--- a/src/host/virt_phy/src/virtphy.c
+++ b/src/host/virt_phy/src/virtphy.c
@@ -17,10 +17,10 @@
int main(void)
{
-
// init loginfo
static struct l1_model_ms *model;
- ms_log_init("DL1C,1:DVIRPHY,1");
+ //ms_log_init("DL1C,1:DVIRPHY,1");
+ ms_log_init("DL1C,1");
//ms_log_init("DL1C,8:DVIRPHY,8");
LOGP(DVIRPHY, LOGL_INFO, "Virtual physical layer starting up...\n");
@@ -28,7 +28,10 @@
model = l1_model_ms_init(NULL);
// TODO: make this configurable
- model->vui = virt_um_init(NULL, DEFAULT_BTS_MCAST_GROUP, DEFAULT_BTS_MCAST_PORT, DEFAULT_MS_MCAST_GROUP, DEFAULT_MS_MCAST_PORT, gsmtapl1_rx_from_virt_um_inst_cb);
+ model->vui = virt_um_init(NULL, DEFAULT_BTS_MCAST_GROUP,
+ DEFAULT_BTS_MCAST_PORT, DEFAULT_MS_MCAST_GROUP,
+ DEFAULT_MS_MCAST_PORT,
+ gsmtapl1_rx_from_virt_um_inst_cb);
model->lsi = l1ctl_sock_init(NULL, l1ctl_sap_rx_from_l23_inst_cb, NULL);
gsmtapl1_init(model);
diff --git a/src/host/virt_phy/src/virtual_um.c b/src/host/virt_phy/src/virtual_um.c
index 2b15509..e2e86e4 100644
--- a/src/host/virt_phy/src/virtual_um.c
+++ b/src/host/virt_phy/src/virtual_um.c
@@ -19,7 +19,6 @@
*
*/
-#include <unistd.h>
#include <osmocom/core/select.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
@@ -46,10 +45,12 @@
int rc;
// read message from fd in message buffer
- rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg), msgb_tailroom(msg));
+ rc = mcast_bidir_sock_rx(vui->mcast_sock, msgb_data(msg),
+ msgb_tailroom(msg));
// rc is number of bytes actually read
if (rc > 0) {
msgb_put(msg, rc);
+ msg->l1h = msgb_data(msg);
// call the l1 callback function for a received msg
vui->recv_cb(vui, msg);
} else {
@@ -68,12 +69,13 @@
struct virt_um_inst *virt_um_init(
void *ctx, const char *tx_mcast_group, uint16_t tx_mcast_port,
- const char *rx_mcast_group, uint16_t rx_mcast_port, void (*recv_cb)(struct virt_um_inst *vui, struct msgb *msg))
+ const char *rx_mcast_group, uint16_t rx_mcast_port,
+ 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);
+ 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);
vui->recv_cb = recv_cb;
return vui;
@@ -93,7 +95,8 @@
{
int rc;
- rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg), msgb_length(msg));
+ rc = mcast_bidir_sock_tx(vui->mcast_sock, msgb_data(msg),
+ msgb_length(msg));
msgb_free(msg);
return rc;
--
To view, visit https://gerrit.osmocom.org/3199
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ibad741d112643c55091b8ba00164b05d728ae1a1
Gerrit-PatchSet: 2
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: BastusIII <sebastian.stumpf87 at googlemail.com>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder