diff options
Diffstat (limited to 'src/host/virt_phy/include/osmocom')
14 files changed, 425 insertions, 0 deletions
diff --git a/src/host/virt_phy/include/osmocom/Makefile.am b/src/host/virt_phy/include/osmocom/Makefile.am new file mode 100644 index 00000000..83c6385c --- /dev/null +++ b/src/host/virt_phy/include/osmocom/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = \ + bb \ + $(NULL) diff --git a/src/host/virt_phy/include/osmocom/bb/Makefile.am b/src/host/virt_phy/include/osmocom/bb/Makefile.am new file mode 100644 index 00000000..9a4b939a --- /dev/null +++ b/src/host/virt_phy/include/osmocom/bb/Makefile.am @@ -0,0 +1,8 @@ +SUBDIRS = \ + virtphy \ + $(NULL) + +noinst_HEADERS = \ + l1ctl_proto.h \ + l1gprs.h \ + $(NULL) diff --git a/src/host/virt_phy/include/osmocom/bb/l1ctl_proto.h b/src/host/virt_phy/include/osmocom/bb/l1ctl_proto.h new file mode 120000 index 00000000..ee19b80e --- /dev/null +++ b/src/host/virt_phy/include/osmocom/bb/l1ctl_proto.h @@ -0,0 +1 @@ +../../../../../../include/l1ctl_proto.h
\ No newline at end of file diff --git a/src/host/virt_phy/include/osmocom/bb/l1gprs.h b/src/host/virt_phy/include/osmocom/bb/l1gprs.h new file mode 120000 index 00000000..3bf85176 --- /dev/null +++ b/src/host/virt_phy/include/osmocom/bb/l1gprs.h @@ -0,0 +1 @@ +../../../../../../include/l1gprs.h
\ No newline at end of file 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); |