diff options
-rw-r--r-- | include/osmo-bts/phy_link.h | 5 | ||||
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_tchf.c | 6 | ||||
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_tchh.c | 5 | ||||
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_xcch.c | 15 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_if.c | 34 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_if.h | 7 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_vty.c | 51 |
7 files changed, 121 insertions, 2 deletions
diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h index 862ed48f..82a32629 100644 --- a/include/osmo-bts/phy_link.h +++ b/include/osmo-bts/phy_link.h @@ -52,6 +52,11 @@ struct phy_link { bool powered; /* last POWERON (true) or POWEROFF (false) confirmed */ bool poweron_sent; /* is there a POWERON in transit? */ bool poweroff_sent; /* is there a POWEROFF in transit? */ + struct { + char *remote_host; + bool all; + struct gsmtap_inst *gti; + } gsmtap_burst; } osmotrx; struct { char *mcast_dev; /* Network device for multicast */ diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c index 9acbf31c..bf011eac 100644 --- a/src/osmo-bts-trx/sched_lchan_tchf.c +++ b/src/osmo-bts-trx/sched_lchan_tchf.c @@ -42,9 +42,11 @@ #include <osmo-bts/scheduler.h> #include <osmo-bts/scheduler_backend.h> #include <osmo-bts/msg_utils.h> +#include <osmo-bts/phy_link.h> #include <sched_utils.h> #include <amr_loop.h> +#include <trx_if.h> /* 3GPP TS 45.009, table 3.2.1.3-{1,3}: AMR on Uplink TCH/F. * @@ -74,6 +76,7 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; struct gsm_lchan *lchan = chan_state->lchan; + struct phy_link *plink = lchan->ts->trx->pinst->phy_link; sbit_t *burst, *bursts_p = chan_state->ul_bursts; uint8_t *mask = &chan_state->ul_mask; uint8_t rsl_cmode = chan_state->rsl_cmode; @@ -267,6 +270,9 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) * Doing so tells l1sap.c to ignore the measurement result. */ meas_avg.rssi = 0; rc = 0; + + if (bfi_flag || OSMO_UNLIKELY(plink->u.osmotrx.gsmtap_burst.all)) + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); } if (rsl_cmode != RSL_CMOD_SPD_SPEECH) diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c index 8d1aab39..ec8bdbc9 100644 --- a/src/osmo-bts-trx/sched_lchan_tchh.c +++ b/src/osmo-bts-trx/sched_lchan_tchh.c @@ -42,9 +42,11 @@ #include <osmo-bts/scheduler.h> #include <osmo-bts/scheduler_backend.h> #include <osmo-bts/msg_utils.h> +#include <osmo-bts/phy_link.h> #include <sched_utils.h> #include <amr_loop.h> +#include <trx_if.h> /* 3GPP TS 45.009, table 3.2.1.3-{2,4}: AMR on Uplink TCH/H. * @@ -96,6 +98,7 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) { struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan]; struct gsm_lchan *lchan = chan_state->lchan; + struct phy_link *plink = lchan->ts->trx->pinst->phy_link; sbit_t *burst, *bursts_p = chan_state->ul_bursts; uint8_t *mask = &chan_state->ul_mask; uint8_t rsl_cmode = chan_state->rsl_cmode; @@ -301,6 +304,8 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) PRES_INFO_UNKNOWN); ber10k = 0; bfi: + if (bfi_flag || OSMO_UNLIKELY(plink->u.osmotrx.gsmtap_burst.all)) + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); /* A FACCH/H frame replaces two speech frames, so we need to send two BFIs. * One is sent here, another will be sent two bursts later (see above). */ rc = 0; diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c index 0fccf3ec..59002666 100644 --- a/src/osmo-bts-trx/sched_lchan_xcch.c +++ b/src/osmo-bts-trx/sched_lchan_xcch.c @@ -32,8 +32,10 @@ #include <osmo-bts/logging.h> #include <osmo-bts/scheduler.h> #include <osmo-bts/scheduler_backend.h> +#include <osmo-bts/phy_link.h> #include <sched_utils.h> +#include <trx_if.h> /* Add two arrays of sbits */ static void add_sbits(sbit_t * current, const sbit_t * previous) @@ -61,6 +63,7 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) int rc; struct gsm_lchan *lchan = chan_state->lchan; bool rep_sacch = L1SAP_IS_LINK_SACCH(trx_chan_desc[bi->chan].link_id) && lchan->rep_acch.ul_sacch_active; + struct phy_link *plink = lchan->ts->trx->pinst->phy_link; /* If handover RACH detection is turned on, treat this burst as an Access Burst. * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */ @@ -128,15 +131,23 @@ int rx_data_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Combining current SACCH block with previous SACCH block also yields bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); + + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); } else { LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi, "Combining current SACCH block with previous SACCH block yields good data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); l2_len = GSM_MACBLOCK_LEN; + if (OSMO_UNLIKELY(plink->u.osmotrx.gsmtap_burst.all)) + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); } - } - } else + } else + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); + } else { l2_len = GSM_MACBLOCK_LEN; + if (OSMO_UNLIKELY(plink->u.osmotrx.gsmtap_burst.all)) + gsmtap_bursts_tx(plink, bi->fn, lchan, bursts_p, 464, n_errors, n_bits_total, &meas_avg); + } ber10k = compute_ber10k(n_bits_total, n_errors); diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c index fef8c22f..0a660d80 100644 --- a/src/osmo-bts-trx/trx_if.c +++ b/src/osmo-bts-trx/trx_if.c @@ -41,6 +41,8 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/bits.h> #include <osmocom/core/fsm.h> +#include <osmocom/core/gsmtap.h> +#include <osmocom/core/gsmtap_util.h> #include <osmo-bts/phy_link.h> #include <osmo-bts/logging.h> @@ -1339,6 +1341,14 @@ int bts_model_phy_link_open(struct phy_link *plink) return -1; } + if (plink->u.osmotrx.gsmtap_burst.remote_host) { + LOGPPHL(plink, DL1C, LOGL_NOTICE, "Opening burst-gsmtap to remote host %s\n", + plink->u.osmotrx.gsmtap_burst.remote_host); + plink->u.osmotrx.gsmtap_burst.gti = gsmtap_source_init2(NULL, 0, + plink->u.osmotrx.gsmtap_burst.remote_host, + GSMTAP_UDP_PORT, 1); + } + /* open the individual instances with their ctrl+data sockets */ llist_for_each_entry(pinst, &plink->instances, list) { struct trx_l1h *l1h = pinst->u.osmotrx.hdl; @@ -1375,6 +1385,11 @@ int bts_model_phy_link_close(struct phy_link *plink) } trx_udp_close(&plink->u.osmotrx.trx_ofd_clk); phy_link_state_set(plink, PHY_LINK_SHUTDOWN); + + if (plink->u.osmotrx.gsmtap_burst.gti) { + gsmtap_source_free(plink->u.osmotrx.gsmtap_burst.gti); + plink->u.osmotrx.gsmtap_burst.gti = NULL; + } return 0; } @@ -1385,3 +1400,22 @@ int trx_if_powered(struct trx_l1h *l1h) struct phy_link *plink = pinst->phy_link; return plink->u.osmotrx.powered; } + +void gsmtap_bursts_tx(const struct phy_link *plink, uint32_t fn, const struct gsm_lchan *lchan, + const sbit_t *sbits, size_t n_sbits, int n_errors, int n_bits_total, + const struct l1sched_meas_set *meas_avg) +{ + struct msgb *msg; + int rc; + + if (!plink->u.osmotrx.gsmtap_burst.gti) + return; + + msg = gsmtap_makemsg_ex(GSMTAP_TYPE_UM_BURST, lchan->ts->trx->arfcn | GSMTAP_ARFCN_F_UPLINK, lchan->ts->nr, + GSMTAP_BURST_NORMAL, lchan->nr, fn, meas_avg->rssi, 0/*snr*/, (const uint8_t *) sbits, n_sbits); + if (msg) { + rc = gsmtap_sendmsg(plink->u.osmotrx.gsmtap_burst.gti, msg); + if (rc < 0) + msgb_free(msg); + } +} diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h index b838b76a..738e7499 100644 --- a/src/osmo-bts-trx/trx_if.h +++ b/src/osmo-bts-trx/trx_if.h @@ -48,3 +48,10 @@ int trx_if_powered(struct trx_l1h *l1h); /* Format negotiation command */ int trx_if_cmd_setformat(struct trx_l1h *l1h, uint8_t ver, trx_if_cmd_generic_cb *cb); + +struct l1sched_meas_avg; +struct phy_link; + +void gsmtap_bursts_tx(const struct phy_link *plink, uint32_t fn, const struct gsm_lchan *lchan, + const sbit_t *sbits, size_t n_sbits, int n_errors, int n_bits_total, + const struct l1sched_meas_set *meas_avg); diff --git a/src/osmo-bts-trx/trx_vty.c b/src/osmo-bts-trx/trx_vty.c index 9cc98052..acf88921 100644 --- a/src/osmo-bts-trx/trx_vty.c +++ b/src/osmo-bts-trx/trx_vty.c @@ -504,6 +504,48 @@ DEFUN(cfg_phy_base_port, cfg_phy_base_port_cmd, return CMD_SUCCESS; } +#define GSMTAP_BURSTS_STR "Configure GSMTAP for raw bursts\n" + +DEFUN_USRATTR(cfg_phy_gsmtap_bursts_host, cfg_phy_gsmtap_bursts_host_cmd, + X(BTS_VTY_TRX_POWERCYCLE), + "osmotrx gsmtap-bursts remote-host " VTY_IPV46_CMD, + OSMOTRX_STR GSMTAP_BURSTS_STR + "Set remote IP address to which send raw bursts in GSMTAP format\n" + "Remote IPv4 address\n" + "Remote IPv6 address\n") +{ + struct phy_link *plink = vty->index; + osmo_talloc_replace_string(plink, &plink->u.osmotrx.gsmtap_burst.remote_host, argv[0]); + return CMD_SUCCESS; +} + +DEFUN_USRATTR(cfg_phy_no_gsmtap_bursts_host, cfg_phy_no_gsmtap_bursts_host_cmd, + X(BTS_VTY_TRX_POWERCYCLE), + "no osmotrx gsmtap-bursts remote-host", + NO_STR OSMOTRX_STR GSMTAP_BURSTS_STR + "Disable sending GSMTAP bust data\n") +{ + struct phy_link *plink = vty->index; + talloc_free(plink->u.osmotrx.gsmtap_burst.remote_host); + plink->u.osmotrx.gsmtap_burst.remote_host = NULL; + return CMD_SUCCESS; +} + +DEFUN(cfg_phy_gsmtap_bursts_type, cfg_phy_gsmtap_bursts_type_cmd, + "osmotrx gsmtap-bursts type (all|crc-error)", + OSMOTRX_STR GSMTAP_BURSTS_STR + "Configure which bursts to send via GSMTAP\n" + "Send all burst as GSMTAP burstss\n" + "Send only bursts with CRC failures as GSMTAP bursts\n") +{ + struct phy_link *plink = vty->index; + if (!strcmp(argv[0], "all")) + plink->u.osmotrx.gsmtap_burst.all = true; + else + plink->u.osmotrx.gsmtap_burst.all = false; + return CMD_SUCCESS; +} + DEFUN_USRATTR(cfg_phy_setbsic, cfg_phy_setbsic_cmd, X(BTS_VTY_TRX_POWERCYCLE), "osmotrx legacy-setbsic", OSMOTRX_STR @@ -580,6 +622,12 @@ void bts_model_config_write_phy(struct vty *vty, const struct phy_link *plink) if (plink->u.osmotrx.trxd_pdu_ver_max != TRX_DATA_PDU_VER) vty_out(vty, " osmotrx trxd-max-version %d%s", plink->u.osmotrx.trxd_pdu_ver_max, VTY_NEWLINE); + + if (plink->u.osmotrx.gsmtap_burst.remote_host) { + vty_out(vty, " osmotrx gsmtap-bursts remote-host %s%s", plink->u.osmotrx.gsmtap_burst.remote_host, VTY_NEWLINE); + vty_out(vty, " osmotrx gsmtap-bursts type %s%s", + plink->u.osmotrx.gsmtap_burst.all ? "all" : "crc-error", VTY_NEWLINE); + } } void bts_model_config_write_phy_inst(struct vty *vty, const struct phy_instance *pinst) @@ -645,6 +693,9 @@ int bts_model_vty_init(void *ctx) install_element(PHY_NODE, &cfg_phy_setbsic_cmd); install_element(PHY_NODE, &cfg_phy_no_setbsic_cmd); install_element(PHY_NODE, &cfg_phy_trxd_max_version_cmd); + install_element(PHY_NODE, &cfg_phy_gsmtap_bursts_host_cmd); + install_element(PHY_NODE, &cfg_phy_no_gsmtap_bursts_host_cmd); + install_element(PHY_NODE, &cfg_phy_gsmtap_bursts_type_cmd); install_element(PHY_INST_NODE, &cfg_phyinst_rxgain_cmd); install_element(PHY_INST_NODE, &cfg_phyinst_tx_atten_cmd); |