summaryrefslogtreecommitdiffstats
path: root/src/host/virt_phy/include/osmocom/bb/virtphy
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/virt_phy/include/osmocom/bb/virtphy')
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/Makefile.am11
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/common_util.h11
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/gsmtapl1_if.h13
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h85
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sock.h53
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/logging.h20
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/osmo_mcast_sock.h29
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h119
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_sched.h34
-rw-r--r--src/host/virt_phy/include/osmocom/bb/virtphy/virtual_um.h37
10 files changed, 412 insertions, 0 deletions
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/Makefile.am b/src/host/virt_phy/include/osmocom/bb/virtphy/Makefile.am
new file mode 100644
index 00000000..75846096
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/Makefile.am
@@ -0,0 +1,11 @@
+noinst_HEADERS = \
+ logging.h \
+ osmo_mcast_sock.h \
+ l1ctl_sock.h \
+ virtual_um.h \
+ gsmtapl1_if.h \
+ virt_l1_sched.h \
+ common_util.h \
+ l1ctl_sap.h \
+ virt_l1_model.h \
+ $(NULL)
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/common_util.h b/src/host/virt_phy/include/osmocom/bb/virtphy/common_util.h
new file mode 100644
index 00000000..2585d069
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/common_util.h
@@ -0,0 +1,11 @@
+/*
+ * Utility function used both in osmo bts virt and osmocom bb virt.
+ */
+
+#pragma once
+
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/gsm/rsl.h>
+
+#define LID_SACCH 0x40
+#define LID_DEDIC 0x00
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/gsmtapl1_if.h b/src/host/virt_phy/include/osmocom/bb/virtphy/gsmtapl1_if.h
new file mode 100644
index 00000000..c9e92525
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/gsmtapl1_if.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/gsmtap.h>
+
+#include <osmocom/bb/virtphy/virtual_um.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+#include <osmocom/bb/virtphy/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_tx_to_virt_um_inst(struct l1_model_ms *ms, uint32_t fn, uint8_t tn, struct msgb *msg);
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h
new file mode 100644
index 00000000..e756c140
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sap.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/msgb.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/l1ctl_proto.h>
+
+/* following sizes are used for message allocation */
+/* size of layer 3 header */
+#define L3_MSG_HEAD 4
+/* size of layer 3 payload */
+#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
+
+/* signature strengths for the ms */
+#define MIN_SIG_LEV_DBM -110
+#define MAX_SIG_LEV_DBM -63
+
+/* Ignore all flags of the arfcn */
+#define ARFCN_NO_FLAGS_MASK 0x0fff
+
+
+void l1ctl_sap_init(struct l1_model_ms *model);
+void l1ctl_sap_exit(struct l1_model_ms *model);
+void prim_pm_init(struct l1_model_ms *model);
+void prim_pm_exit(struct l1_model_ms *model);
+void l1ctl_sap_tx_to_l23_inst(struct l1_model_ms *model, struct msgb *msg);
+void l1ctl_sap_rx_from_l23_inst_cb(struct l1ctl_sock_client *lsc, struct msgb *msg);
+void l1ctl_sap_handler(struct l1_model_ms *ms, struct msgb *msg);
+
+/* utility methods */
+struct msgb *l1ctl_msgb_alloc(uint8_t msg_type);
+struct msgb *l1ctl_create_l2_msg(int msg_type, uint32_t fn, uint16_t snr,
+ uint16_t arfcn);
+
+/* receive routines */
+void l1ctl_rx_fbsb_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_dm_est_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_dm_rel_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_param_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_dm_freq_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_crypto_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_rach_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_data_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_pm_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_reset_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_ccch_mode_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_tch_mode_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_neigh_pm_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_traffic_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_sim_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_gprs_uldl_tbf_cfg_req(struct l1_model_ms *ms, struct msgb *msg);
+void l1ctl_rx_gprs_ul_block_req(struct l1_model_ms *ms, struct msgb *msg);
+
+/* transmit routines */
+void l1ctl_tx_reset(struct l1_model_ms *ms, uint8_t msg_type, uint8_t reset_type);
+void l1ctl_tx_rach_conf(struct l1_model_ms *ms, uint32_t fn, uint16_t arfcn);
+void l1ctl_tx_data_conf(struct l1_model_ms *ms, uint32_t fn, uint16_t snr, uint16_t arfcn);
+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 rxlev, uint8_t num_biterr,
+ uint8_t fire_crc);
+void l1ctl_tx_traffic_conf(struct l1_model_ms *ms, uint32_t fn, uint16_t snr, uint16_t arfcn);
+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 rxlev, uint8_t num_biterr,
+ uint8_t fire_crc);
+void l1ctl_tx_pm_conf(struct l1_model_ms *ms, struct l1ctl_pm_req *pm_req);
+void l1ctl_tx_fbsb_conf(struct l1_model_ms *ms, uint8_t res, uint16_t arfcn);
+void l1ctl_tx_ccch_mode_conf(struct l1_model_ms *ms, uint8_t ccch_mode);
+void l1ctl_tx_tch_mode_conf(struct l1_model_ms *ms, uint8_t tch_mode, uint8_t audio_mode);
+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);
+
+/* scheduler functions */
+uint32_t sched_fn_ul(struct gsm_time cur_time, uint8_t chan_nr,
+ uint8_t link_id);
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sock.h b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sock.h
new file mode 100644
index 00000000..2c98fa58
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/l1ctl_sock.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/select.h>
+
+#define L1CTL_SOCK_PATH "/tmp/osmocom_l2"
+
+struct l1ctl_sock_inst;
+
+struct l1ctl_sock_client {
+ /* list head in l1ctl_sock_inst.clients */
+ struct llist_head list;
+ /* pointer back to the server socket that accepted us */
+ struct l1ctl_sock_inst *l1ctl_sock;
+ /* Osmo FD for the client socket */
+ struct osmo_fd ofd;
+ /* private data, can be set in accept_cb */
+ void *priv;
+};
+
+/* L1CTL socket instance contains socket data. */
+struct l1ctl_sock_inst {
+ void *priv; /* Will be appended after osmo-fd's data pointer. */
+ struct llist_head clients;
+ char* l1ctl_sock_path; /* Socket path used to connect to l23 */
+ struct osmo_fd ofd; /* Osmocom file descriptor to accept L1CTL connections. */
+ void (*recv_cb)(struct l1ctl_sock_client *lsc, struct msgb *msg); /* Callback function called for incoming data from l2 app. */
+ /* Callback function called for new client after accept() */
+ int (*accept_cb)(struct l1ctl_sock_client *lsc);
+ /* Callback function called when client disappeared */
+ void (*close_cb)(struct l1ctl_sock_client *lsc);
+};
+
+/**
+ * @brief Initialise the l1ctl socket for communication with l2 apps.
+ */
+struct l1ctl_sock_inst *l1ctl_sock_init(
+ void *ctx,
+ void (*recv_cb)(struct l1ctl_sock_client *lsc, struct msgb *msg),
+ int (*accept_cb)(struct l1ctl_sock_client *lsc),
+ void (*close_cb)(struct l1ctl_sock_client *lsc),
+ char *path);
+
+/**
+ * @brief Transmit message to l2.
+ */
+int l1ctl_sock_write_msg(struct l1ctl_sock_client *lsc, struct msgb *msg);
+
+/**
+ * @brief Destroy instance.
+ */
+void l1ctl_sock_destroy(struct l1ctl_sock_inst *lsi);
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h b/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h
new file mode 100644
index 00000000..1727453e
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/logging.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <osmocom/core/logging.h>
+
+/* L1CTL related messages */
+enum virtphy_log_cat {
+ DL1C,
+ DL1P,
+ DVIRPHY,
+ DGPRS,
+ DMAIN
+};
+
+#define LOGPMS(ss, lvl, ms, fmt, args ...) LOGP(ss, lvl, "MS %04u: " fmt, ms->nr, ## args)
+#define DEBUGPMS(ss, ms, fmt, args ...) DEBUGP(ss, "MS %04u: " fmt, ms->nr, ## args)
+
+extern const struct log_info ms_log_info;
+
+int ms_log_init(void *ctx, const char *cat_mask);
+const char *getL1ctlPrimName(uint8_t type);
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/osmo_mcast_sock.h b/src/host/virt_phy/include/osmocom/bb/virtphy/osmo_mcast_sock.h
new file mode 100644
index 00000000..aa2013c6
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/osmo_mcast_sock.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <netinet/in.h>
+#include <osmocom/core/select.h>
+
+struct mcast_bidir_sock {
+ struct osmo_fd tx_ofd;
+ struct osmo_fd rx_ofd;
+};
+
+struct mcast_bidir_sock *mcast_bidir_sock_setup(void *ctx,
+ const char *tx_mcast_group, uint16_t tx_mcast_port,
+ const char *rx_mcast_group, uint16_t rx_mcast_port, bool loopback,
+ int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
+ void *osmo_fd_data);
+
+int mcast_server_sock_setup(struct osmo_fd *ofd, const char *tx_mcast_group,
+ uint16_t tx_mcast_port, bool loopback);
+
+int mcast_client_sock_setup(struct osmo_fd *ofd, const char *mcast_group, uint16_t mcast_port,
+ int (*fd_rx_cb)(struct osmo_fd *ofd, unsigned int what),
+ void *osmo_fd_data);
+
+int mcast_bidir_sock_tx(struct mcast_bidir_sock *bidir_sock, const uint8_t *data, unsigned int data_len);
+int mcast_bidir_sock_rx(struct mcast_bidir_sock *bidir_sock, uint8_t *buf, unsigned int buf_len);
+void mcast_bidir_sock_close(struct mcast_bidir_sock* bidir_sock);
+
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h
new file mode 100644
index 00000000..94581f61
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_model.h
@@ -0,0 +1,119 @@
+#pragma once
+
+/* Per-MS specific state, closely attached to the L1CTL user progran */
+
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/timer.h>
+
+#include <osmocom/bb/virtphy/virtual_um.h>
+#include <osmocom/bb/virtphy/l1ctl_sock.h>
+
+#define L1S_NUM_NEIGH_CELL 6
+#define A5_KEY_LEN 8
+
+enum ms_state {
+ MS_STATE_IDLE_SEARCHING = 0,
+ MS_STATE_IDLE_SYNCING,
+ MS_STATE_IDLE_CAMPING,
+ MS_STATE_DEDICATED,
+};
+
+
+/* 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 */
+ /* what's 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 {
+
+ struct gsm_time downlink_time; /* current GSM time received on downlink */
+ struct gsm_time current_time; /* GSM time used internally for scheduling */
+ struct {
+ uint32_t last_exec_fn;
+ struct llist_head mframe_items;
+ } sched;
+
+ enum ms_state state;
+
+ /* 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];
+ struct crypto_info_ms crypto_inf;
+
+ /* 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 */
+
+ uint16_t band_arfcn;
+ uint8_t tn; // timeslot number 1-7
+ uint8_t subslot; // subslot of the dedicated channel, SDCCH/4:[0-3], SDCCH/8:[0-7]
+
+ uint8_t scn; // single-hop cellular network? (unused in virtual um)
+ uint8_t tsc; // training sequence code (unused in virtual um)
+ uint8_t h; // hopping enabled flag (unused in virtual um)
+ } dedicated;
+
+ /* fbsb state */
+ struct {
+ uint32_t arfcn;
+ } fbsb;
+
+ /* power management state */
+ struct {
+ uint32_t timeout_us;
+ uint32_t timeout_s;
+ struct {
+ int16_t arfcn_sig_lev_dbm[1024];
+ uint8_t arfcn_sig_lev_red_dbm[1024];
+ struct osmo_timer_list arfcn_sig_lev_timers[1024];
+ } meas;
+ struct {
+ uint16_t band_arfcn_from;
+ uint16_t band_arfcn_to;
+ /* timer between receiving PM_REQ and responding with PM_CONF */
+ struct osmo_timer_list timer;
+ } req;
+ } pm;
+};
+
+struct l1_model_ms {
+ uint32_t nr;
+ /* pointer to the L1CTL socket client associated with this specific MS */
+ struct l1ctl_sock_client *lsc;
+ /* pointer to the (shared) GSMTAP/VirtUM socket to talk to BTS(s) */
+ struct virt_um_inst *vui;
+ /* GPRS state (MAC layer) */
+ struct l1gprs_state *gprs;
+ /* actual per-MS state */
+ struct l1_state_ms state;
+};
+
+
+struct l1_model_ms *l1_model_ms_init(void *ctx, struct l1ctl_sock_client *lsc, struct virt_um_inst *vui);
+
+void l1_model_ms_destroy(struct l1_model_ms *model);
+
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_sched.h b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_sched.h
new file mode 100644
index 00000000..d5a1630f
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/virt_l1_sched.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/gsm_utils.h>
+
+#include <osmocom/bb/virtphy/virt_l1_model.h>
+#include <osmocom/bb/virtphy/virt_l1_sched.h>
+
+struct l1_model_ms;
+
+typedef void virt_l1_sched_cb(struct l1_model_ms *ms, uint32_t fn, uint8_t tn, struct msgb * msg);
+
+/* bucket containing items to be executed for a specific mframe number */
+struct virt_l1_sched_mframe_item {
+ struct llist_head mframe_item_entry;
+ struct llist_head tdma_item_list; /* list of tdma sched items */
+ uint32_t fn; /* frame number of execution */
+};
+
+/* item to be be executed for a specific tdma timeslot of a framenumber */
+struct virt_l1_sched_tdma_item {
+ struct llist_head tdma_item_entry;
+ struct msgb * msg; /* the msg to be handled */
+ uint8_t ts; /* tdma timeslot of execution */
+ virt_l1_sched_cb * handler_cb; /* handler callback */
+};
+
+int virt_l1_sched_restart(struct l1_model_ms *ms, struct gsm_time time);
+void virt_l1_sched_sync_time(struct l1_model_ms *ms, struct gsm_time time, uint8_t hard_reset);
+void virt_l1_sched_stop(struct l1_model_ms *ms);
+void virt_l1_sched_execute(struct l1_model_ms *ms, uint32_t fn);
+void virt_l1_sched_schedule(struct l1_model_ms *ms, struct msgb *msg, uint32_t fn, uint8_t ts,
+ virt_l1_sched_cb * handler_cb);
diff --git a/src/host/virt_phy/include/osmocom/bb/virtphy/virtual_um.h b/src/host/virt_phy/include/osmocom/bb/virtphy/virtual_um.h
new file mode 100644
index 00000000..fe060929
--- /dev/null
+++ b/src/host/virt_phy/include/osmocom/bb/virtphy/virtual_um.h
@@ -0,0 +1,37 @@
+#pragma once
+
+/* the "Virtual Um instance" encapsulates the multicast UDP sockets as
+ * well as the encoding and decoding of GSMTAP messages towards the
+ * virtual radio interface. It receives DL messages via GSMTAP from any
+ * number of BTSs transmitting to GSMTAP, and transmits UL messages via
+ * GSMTAP to those BTSs in another multicast group */
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+#include "osmo_mcast_sock.h"
+
+/* We use multicast group addresses from the 239.192.0.0/14 rage, as
+ * those are designated by RFC2365 as "IPv4 Organization Local Scope,
+ * "... the space from which an organization should allocate sub-
+ * ranges when defining scopes for private use." */
+
+#define VIRT_UM_MSGB_SIZE 256
+#define DEFAULT_MS_MCAST_GROUP "239.193.23.1"
+#define DEFAULT_MS_MCAST_PORT 4729 /* IANA-registered port for GSMTAP */
+#define DEFAULT_BTS_MCAST_GROUP "239.193.23.2"
+#define DEFAULT_BTS_MCAST_PORT 4729 /* IANA-registered port for GSMTAP */
+
+struct virt_um_inst {
+ void *priv;
+ struct mcast_bidir_sock *mcast_sock;
+ 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));
+
+void virt_um_destroy(struct virt_um_inst *vui);
+
+int virt_um_write_msg(struct virt_um_inst *vui, struct msgb *msg);