aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-04-19 22:29:07 +0200
committerHarald Welte <laforge@gnumonks.org>2012-04-19 22:29:07 +0200
commit2b7aace0b5092d2a0e3d639bdc2760934105d3e1 (patch)
tree982d72cfc997d6b23d6303ad8f0da3bcfcb8d680 /src
parentb1644b22d0786133b28f2af3bffa5f22ffe222d2 (diff)
add vty-configurable loopback mode
this allows the BTS to loop-back any incoming data on a TCH
Diffstat (limited to 'src')
-rw-r--r--src/osmo-bts-sysmo/l1_if.c2
-rw-r--r--src/osmo-bts-sysmo/sysmobts_vty.c42
-rw-r--r--src/osmo-bts-sysmo/tch.c40
3 files changed, 83 insertions, 1 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index c11c0cd9..9b6100cc 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -375,7 +375,7 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
if (!lchan)
break;
- if (lchan->abis_ip.rtp_socket) {
+ if (!lchan->loopback && lchan->abis_ip.rtp_socket) {
osmo_rtp_socket_poll(lchan->abis_ip.rtp_socket);
/* FIXME: we _assume_ that we never miss TDMA
* frames and that we always get to this point
diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c
index c1bcfa71..fe035a40 100644
--- a/src/osmo-bts-sysmo/sysmobts_vty.c
+++ b/src/osmo-bts-sysmo/sysmobts_vty.c
@@ -344,6 +344,45 @@ DEFUN(set_tx_power, set_tx_power_cmd,
return CMD_SUCCESS;
}
+DEFUN(loopback, loopback_cmd,
+ "trx <0-0> <0-7> loopback <0-1>",
+ TRX_STR
+ "Timeslot number\n"
+ "Set TCH loopback\n"
+ "Logical Channel Number\n")
+{
+ int trx_nr = atoi(argv[0]);
+ int ts_nr = atoi(argv[1]);
+ int lchan_nr = atoi(argv[2]);
+ struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
+ struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
+ struct gsm_lchan *lchan = &ts->lchan[lchan_nr];
+
+ lchan->loopback = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_loopback, no_loopback_cmd,
+ "no trx <0-0> <0-7> loopback <0-1>",
+ NO_STR TRX_STR
+ "Timeslot number\n"
+ "Set TCH loopback\n"
+ "Logical Channel Number\n")
+{
+ int trx_nr = atoi(argv[0]);
+ int ts_nr = atoi(argv[1]);
+ int lchan_nr = atoi(argv[2]);
+ struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
+ struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
+ struct gsm_lchan *lchan = &ts->lchan[lchan_nr];
+
+ lchan->loopback = 0;
+
+ return CMD_SUCCESS;
+}
+
+
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
}
@@ -381,6 +420,9 @@ int bts_model_vty_init(struct gsm_bts *bts)
install_element(ENABLE_NODE, &activate_lchan_cmd);
install_element(ENABLE_NODE, &set_tx_power_cmd);
+ install_element(ENABLE_NODE, &loopback_cmd);
+ install_element(ENABLE_NODE, &no_loopback_cmd);
+
install_element(TRX_NODE, &cfg_trx_clkcal_cmd);
install_element(TRX_NODE, &cfg_trx_clkcal_def_cmd);
install_element(TRX_NODE, &cfg_trx_clksrc_cmd);
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c
index a63910f8..c6c782fa 100644
--- a/src/osmo-bts-sysmo/tch.c
+++ b/src/osmo-bts-sysmo/tch.c
@@ -443,6 +443,10 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl,
DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan),
osmo_hexdump(rtp_pl, rtp_pl_len));
+ /* skip processing of incoming RTP frames if we are in loopback mode */
+ if (lchan->loopback)
+ return;
+
msg = l1p_msgb_alloc();
if (!msg) {
LOGP(DRTP, LOGL_ERROR, "%s: Failed to allocate Rx payload.\n",
@@ -538,6 +542,42 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg)
}
payload_len = data_ind->msgUnitParam.u8Size - 1;
+ if (lchan->loopback) {
+ GsmL1_Prim_t *rl1p;
+ GsmL1_PhDataReq_t *data_req;
+ GsmL1_MsgUnitParam_t *msu_param;
+
+ struct msgb *tmp;
+ int count = 0;
+
+ /* generate a new msgb from the paylaod */
+ rmsg = l1p_msgb_alloc();
+ if (!rmsg)
+ return -ENOMEM;
+
+ rl1p = msgb_l1prim(rmsg);
+ data_req = &rl1p->u.phDataReq;
+ msu_param = &data_req->msgUnitParam;
+
+ memcpy(msu_param->u8Buffer,
+ data_ind->msgUnitParam.u8Buffer,
+ data_ind->msgUnitParam.u8Size);
+ msu_param->u8Size = data_ind->msgUnitParam.u8Size;
+
+ /* make sure the queue doesn't get too long */
+ llist_for_each_entry(tmp, &lchan->dl_tch_queue, list)
+ count++;
+ while (count >= 1) {
+ tmp = msgb_dequeue(&lchan->dl_tch_queue);
+ msgb_free(tmp);
+ count--;
+ }
+
+ msgb_enqueue(&lchan->dl_tch_queue, rmsg);
+
+ return 0;
+ }
+
switch (payload_type) {
case GsmL1_TchPlType_Fr:
#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE)