aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-01-09 13:13:37 +0100
committerHarald Welte <laforge@gnumonks.org>2016-02-15 14:18:59 +0100
commitd784e50747b8cf0ce505489e1451f75be5ccbd4b (patch)
treeb143bbf2162bea0959ba9b80cc5d1573de7d62ee
parentf58542899a91d1db0bbe9966ae98ccdf449f45d0 (diff)
Introduce new phy_link and phy_instance abstraction
This way we can model a flexible mapping between any number of PHYs, each having multiple instances, and then map BTSs with TRXx on top of those PHYs.
-rw-r--r--doc/examples/octphy/osmo-bts.cfg8
-rw-r--r--doc/phy_link.txt57
-rw-r--r--doc/startup.txt42
-rw-r--r--include/osmo-bts/Makefile.am2
-rw-r--r--include/osmo-bts/bts.h2
-rw-r--r--include/osmo-bts/bts_model.h8
-rw-r--r--include/osmo-bts/gsm_data.h15
-rw-r--r--include/osmo-bts/phy_link.h115
-rw-r--r--include/osmo-bts/scheduler.h4
-rw-r--r--include/osmo-bts/vty.h7
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/bts.c30
-rw-r--r--src/common/main.c20
-rw-r--r--src/common/phy_link.c159
-rw-r--r--src/common/scheduler.c6
-rw-r--r--src/common/vty.c194
-rw-r--r--src/osmo-bts-octphy/l1_if.c170
-rw-r--r--src/osmo-bts-octphy/l1_if.h31
-rw-r--r--src/osmo-bts-octphy/l1_oml.c163
-rw-r--r--src/osmo-bts-octphy/main.c3
-rw-r--r--src/osmo-bts-octphy/octphy_hw_api.c14
-rw-r--r--src/osmo-bts-octphy/octphy_vty.c198
-rw-r--r--src/osmo-bts-trx/l1_if.c84
-rw-r--r--src/osmo-bts-trx/l1_if.h18
-rw-r--r--src/osmo-bts-trx/main.c78
-rw-r--r--src/osmo-bts-trx/scheduler_trx.c33
-rw-r--r--src/osmo-bts-trx/trx_if.c133
-rw-r--r--src/osmo-bts-trx/trx_if.h1
-rw-r--r--src/osmo-bts-trx/trx_vty.c381
29 files changed, 1424 insertions, 554 deletions
diff --git a/doc/examples/octphy/osmo-bts.cfg b/doc/examples/octphy/osmo-bts.cfg
index 07bcae0..4f27c8d 100644
--- a/doc/examples/octphy/osmo-bts.cfg
+++ b/doc/examples/octphy/osmo-bts.cfg
@@ -20,9 +20,13 @@ log stderr
line vty
no login
!
+phy 0
+ octphy hw-addr 00:0C:90:2e:80:1e
+ octphy net-device eth0.2342
+ instance 0
bts 0
band 1800
ipa unit-id 1234 0
oml remote-ip 127.0.0.1
- phy-hw-addr 00:0C:90:2e:80:1e
- phy-netdev eth0.2342
+ trx 0
+ phy 0 instance 0
diff --git a/doc/phy_link.txt b/doc/phy_link.txt
new file mode 100644
index 0000000..c49e328
--- /dev/null
+++ b/doc/phy_link.txt
@@ -0,0 +1,57 @@
+
+== OsmoBTS PHY interface abstraction
+
+The OsmoBTS PHY interface serves as an abstraction layer between given
+PHY hardware and the actual logical transceivers (TRXs) of a BTS inside
+the OsmoBTS code base.
+
+
+=== PHY link
+
+A PHY link is a physical connection / link towards a given PHY. This
+might be, for example,
+
+* a set of file descriptors to device nodes in the /dev/ directory
+ (sysmobts, litecell15)
+* a packet socket for sending raw Ethernet frames to an OCTPHY
+* a set of UDP sockets for interacting with OsmoTRX
+
+Each PHY interface has a set of attribute/parameters and a list of 1 to
+n PHY instances.
+
+PHY links are numbered 0..n globally inside OsmoBTS.
+
+Each PHY link is configured via the VTY using its individual top-level
+vty node. Given the different bts-model / phy specific properties, the
+VTY configuration options (if any) of the PHY instance differ between
+BTS models.
+
+The PHY links and instances must be configured above the BTS/TRX nodes
+in the configuration file. If the file is saved via the VTY, the code
+automatically ensures this.
+
+
+=== PHY instance
+
+A PHY instance is an instance of a PHY, accessed via a PHY link.
+
+In the case of osmo-bts-sysmo and osmo-bts-trx, there is only one
+instance in every PHY link. This is due to the fact that the API inside
+that PHY link does not permit for distinguishing multiple different
+logical TRXs.
+
+Other PHY implementations like the OCTPHY however do support addressing
+multiple PHY instances via a single PHY link.
+
+PHY instances are numbered 0..n inside each PHY link.
+
+Each PHY instance is configured via the VTY as a separate node beneath each
+PHY link. Given the different bts-model / phy specific properties, the
+VTY configuration options (if any) of the PHY instance differ between
+BTS models.
+
+
+=== Mapping PHY instances to TRXs
+
+Each TRX node in the VTY must use the 'phy N instance M' command in
+order to specify which PHY instance is allocated to this specific TRX.
diff --git a/doc/startup.txt b/doc/startup.txt
new file mode 100644
index 0000000..cc64375
--- /dev/null
+++ b/doc/startup.txt
@@ -0,0 +1,42 @@
+
+== start-up / sequencing during OsmoBTS start
+
+The start-up procedure of OsmoBTS can be described as follows:
+
+|===
+| bts-specific | main() |
+| common | bts_main() | initialization of talloc contexts
+| common | bts_log_init() | initialization of logging
+| common | handle_options() | common option parsing
+| bts-specific | bts_model_handle_options() | model-specific option parsing
+| common | gsm_bts_alloc() | allocation of BTS/TRX/TS data structures
+| common | vty_init() | Initialziation of VTY core, libosmo-abis and osmo-bts VTY
+| common | main() | Setting of scheduler RR priority (if configured)
+| common | main() | Initialization of GSMTAP (if configured)
+| common | bts_init() | configuration of defaults in bts/trx/s object
+| bts-specific | bts_model_init | ?
+| common | abis_init() | Initialization of libosmo-abis
+| common | vty_read_config_file() | Reading of configuration file
+| bts-specific | bts_model_phy_link_set_defaults() | Called for every PHY link created
+| bts-specific | bts_model_phy_instance_set_defaults() | Called for every PHY Instance created
+| common | bts_controlif_setup() | Initialization of Control Interface
+| bts-specific | bts_model_ctrl_cmds_install()
+| common | telnet_init() | Initialization of telnet interface
+| common | pcu_sock_init() | Initializaiton of PCU socket
+| common | main() | Installation of signal handlers
+| common | abis_open() | Start of the A-bis connection to BSC
+| common | phy_links_open() | Iterate over list of configured PHY links
+| bts-specific | bts_model_phy_link_open() | Open each of the configured PHY links
+| common | write_pid_file() | Generate the pid file
+| common | osmo_daemonize() | Fork as daemon in background (if configured)
+| common | bts_main() | Run main loop until global variable quit >= 2
+| bts-specific | bts_model_oml_estab() | Called by core once OML link is established
+| bts-specific | bts_model_check_oml() | called each time OML sets some attributes on a MO, checks if attributes are valid
+| bts-specific | bts_model_apply_oml() | called each time OML sets some attributes on a MO, stores attribute contents in data structures
+| bts-specific | bts_model_opstart() | for NM_OC_BTS, NM_OC_SITE_MANAGER, NM_OC_GPRS_NSE, NM_OC_GPRS_CELL, NMO_OC_GPRS_NSVC
+| bts-specific | bts_model_opstart() | for NM_OC_RADIO_CARRIER for each trx
+| bts-specific | bts_model_opstart() | for NM_OC_BASEB_TRANSC for each trx
+| bts-specific | bts_model_opstart() | for NM_OC_CHANNEL for each timeslot on each trx
+| bts-specific | bts_model_change_power() | change transmit power for each trx (power ramp-up/ramp-down
+
+| bts-specific | bts_model_abis_close() | called when either one of the RSL links or the OML link are down
diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am
index af88a1a..d0b55ff 100644
--- a/include/osmo-bts/Makefile.am
+++ b/include/osmo-bts/Makefile.am
@@ -1,4 +1,4 @@
noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \
oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \
handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \
- power_control.h scheduler.h scheduler_backend.h
+ power_control.h scheduler.h scheduler_backend.h phy_link.h
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 9e21186..ec58edd 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -21,12 +21,12 @@ void destroy_bts(struct gsm_bts *bts);
int work_bts(struct gsm_bts *bts);
int bts_link_estab(struct gsm_bts *bts);
int trx_link_estab(struct gsm_bts_trx *trx);
+int trx_set_available(struct gsm_bts_trx *trx, int avail);
void bts_new_si(void *arg);
void bts_setup_slot(struct gsm_bts_trx_ts *slot, uint8_t comb);
int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg);
struct msgb *bts_agch_dequeue(struct gsm_bts *bts);
-void bts_update_agch_max_queue_length(struct gsm_bts *bts);
int bts_agch_max_queue_length(int T, int bcch_conf);
int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
int is_ag_res);
diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h
index 41b5e93..6252557 100644
--- a/include/osmo-bts/bts_model.h
+++ b/include/osmo-bts/bts_model.h
@@ -8,6 +8,9 @@
#include <osmo-bts/gsm_data.h>
+struct phy_link;
+struct phy_instance;
+
/* BTS model specific functions needed by the common code */
int bts_model_init(struct gsm_bts *bts);
@@ -32,6 +35,8 @@ int bts_model_vty_init(struct gsm_bts *bts);
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts);
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx);
+void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink);
+void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst);
int bts_model_oml_estab(struct gsm_bts *bts);
@@ -47,4 +52,7 @@ int bts_model_ctrl_cmds_install(struct gsm_bts *bts);
int bts_model_handle_options(int argc, char **argv);
void bts_model_print_help();
+void bts_model_phy_link_set_defaults(struct phy_link *plink);
+void bts_model_phy_instance_set_defaults(struct phy_instance *pinst);
+
#endif
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 6a7bca8..f9e6ed1 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -119,21 +119,6 @@ enum lchan_ciph_state {
#include "openbsc/gsm_data_shared.h"
-struct femtol1_hdl;
-
-static inline struct femtol1_hdl *trx_femtol1_hdl(struct gsm_bts_trx *trx)
-{
- return trx->role_bts.l1h;
-}
-
-struct trx_l1h;
-
-static inline struct trx_l1h *trx_l1h_hdl(struct gsm_bts_trx *trx)
-{
- return trx->role_bts.l1h;
-}
-
-
void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state);
/* cipher code */
diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h
new file mode 100644
index 0000000..b9fc412
--- /dev/null
+++ b/include/osmo-bts/phy_link.h
@@ -0,0 +1,115 @@
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <osmo-bts/scheduler.h>
+
+#include <linux/if_packet.h>
+
+struct gsm_bts_trx;
+
+enum phy_link_type {
+ PHY_LINK_T_NONE,
+ PHY_LINK_T_SYSMOBTS,
+ PHY_LINK_T_OSMOTRX,
+};
+
+enum phy_link_state {
+ PHY_LINK_SHUTDOWN,
+ PHY_LINK_CONNECTING,
+ PHY_LINK_CONNECTED,
+};
+
+/* A PHY link represents the connection to a given PHYsical layer
+ * implementation. That PHY link contains 1...N PHY instances, one for
+ * each TRX */
+struct phy_link {
+ struct llist_head list;
+ int num;
+ enum phy_link_type type;
+ enum phy_link_state state;
+ struct llist_head instances;
+ char *description;
+ union {
+ struct {
+ } sysmobts;
+ struct {
+ char *transceiver_ip;
+ uint16_t base_port_local;
+ uint16_t base_port_remote;
+ struct osmo_fd trx_ofd_clk;
+
+ uint32_t clock_advance;
+ uint32_t rts_advance;
+
+ int rxgain_valid;
+ int rxgain;
+ int rxgain_sent;
+
+ int power_valid;
+ int power;
+ int power_oml;
+ int power_sent;
+ } osmotrx;
+ struct {
+ /* MAC address of the PHY */
+ struct sockaddr_ll phy_addr;
+ /* Network device name */
+ char *netdev_name;
+
+ /* configuration */
+ uint32_t rf_port_index;
+ uint32_t rx_gain_db;
+ uint32_t tx_atten_db;
+
+ struct octphy_hdl *hdl;
+ } octphy;
+ } u;
+};
+
+struct phy_instance {
+ /* liked inside phy_link.linstances */
+ struct llist_head list;
+ int num;
+ char *description;
+
+ /* pointer to the PHY link to which we belong */
+ struct phy_link *phy_link;
+
+ /* back-pointer to the TRX to which we're associated */
+ struct gsm_bts_trx *trx;
+
+ union {
+ struct {
+ } sysmobts;
+ struct {
+ struct trx_l1h *hdl;
+ } osmotrx;
+ struct {
+ /* logical transceiver number within one PHY */
+ uint32_t trx_id;
+ } octphy;
+ } u;
+};
+
+struct phy_link *phy_link_by_num(int num);
+struct phy_link *phy_link_create(void *ctx, int num);
+void phy_link_destroy(struct phy_link *plink);
+void phy_link_state_set(struct phy_link *plink, enum phy_link_state state);
+int phy_links_open(void);
+
+struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num);
+struct phy_instance *phy_instance_create(struct phy_link *plink, int num);
+void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx);
+void phy_instance_destroy(struct phy_instance *pinst);
+const char *phy_instance_name(struct phy_instance *pinst);
+
+void phy_user_statechg_notif(struct phy_instance *pinst, enum phy_link_state link_state);
+
+static inline struct phy_instance *trx_phy_instance(struct gsm_bts_trx *trx)
+{
+ return trx->role_bts.l1h;
+}
+
+int bts_model_phy_link_open(struct phy_link *plink);
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 13ef051..b11e6f1 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -1,6 +1,8 @@
#ifndef TRX_SCHEDULER_H
#define TRX_SCHEDULER_H
+#include <osmo-bts/gsm_data.h>
+
/* These types define the different channels on a multiframe.
* Each channel has queues and can be activated individually.
*/
@@ -133,7 +135,7 @@ extern uint32_t transceiver_last_fn;
/*! \brief Initialize the scheudler data structures */
-int trx_sched_init(struct l1sched_trx *l1t);
+int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx);
/*! \brief De-initialize the scheudler data structures */
void trx_sched_exit(struct l1sched_trx *l1t);
diff --git a/include/osmo-bts/vty.h b/include/osmo-bts/vty.h
index 546729c..5d8d4a7 100644
--- a/include/osmo-bts/vty.h
+++ b/include/osmo-bts/vty.h
@@ -5,7 +5,12 @@
#include <osmocom/vty/command.h>
enum bts_vty_node {
- BTS_NODE = _LAST_OSMOVTY_NODE + 1,
+ /* PHY_NODE must come before BTS node to ensure the phy
+ * instances are created at the time the TRX nodes want to refer
+ * to them */
+ PHY_NODE = _LAST_OSMOVTY_NODE + 1,
+ PHY_INST_NODE,
+ BTS_NODE,
TRX_NODE,
};
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index fea205c..8df6513 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -8,6 +8,6 @@ libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
load_indication.c pcu_sock.c handover.c msg_utils.c \
load_indication.c pcu_sock.c handover.c msg_utils.c \
tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \
- l1sap.c cbch.c power_control.c main.c
+ l1sap.c cbch.c power_control.c main.c phy_link.c
libl1sched_a_SOURCES = scheduler.c
diff --git a/src/common/bts.c b/src/common/bts.c
index 43f4c25..2d0ad8e 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -44,6 +44,7 @@
#include <osmo-bts/oml.h>
#include <osmo-bts/signal.h>
+static void bts_update_agch_max_queue_length(struct gsm_bts *bts);
struct gsm_network bts_gsmnet = {
.bts_list = { &bts_gsmnet.bts_list, &bts_gsmnet.bts_list },
@@ -72,6 +73,8 @@ static int bts_signal_cbfn(unsigned int subsys, unsigned int signal,
return 0;
}
+/* Initialize the BTS (and TRX) data structures, called before config
+ * file reading */
int bts_init(struct gsm_bts *bts)
{
struct gsm_bts_role_bts *btsb;
@@ -255,6 +258,31 @@ int trx_link_estab(struct gsm_bts_trx *trx)
return 0;
}
+/* set the availability of the TRX (used by PHY driver) */
+int trx_set_available(struct gsm_bts_trx *trx, int avail)
+{
+ int tn;
+
+ LOGP(DSUM, LOGL_INFO, "TRX(%d): Setting available = %d\n",
+ trx->nr, avail);
+ if (avail) {
+ oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
+ oml_mo_tx_sw_act_rep(&trx->mo);
+ oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OK);
+ oml_mo_tx_sw_act_rep(&trx->bb_transc.mo);
+
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
+ oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY);
+ } else {
+ oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+ oml_mo_state_chg(&trx->bb_transc.mo, -1, NM_AVSTATE_OFF_LINE);
+
+ for (tn = 0; tn < ARRAY_SIZE(trx->ts); tn++)
+ oml_mo_state_chg(&trx->ts[tn].mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+ }
+ return 0;
+}
+
int lchan_init_lapdm(struct gsm_lchan *lchan)
{
struct lapdm_channel *lc = &lchan->lapdm_ch;
@@ -310,7 +338,7 @@ int bts_agch_max_queue_length(int T, int bcch_conf)
return (T + 2 * S) * ccch_rach_ratio256 / 256;
}
-void bts_update_agch_max_queue_length(struct gsm_bts *bts)
+static void bts_update_agch_max_queue_length(struct gsm_bts *bts)
{
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
struct gsm48_system_information_type_3 *si3;
diff --git a/src/common/main.c b/src/common/main.c
index fabe482..e454a28 100644
--- a/src/common/main.c
+++ b/src/common/main.c
@@ -42,6 +42,7 @@
#include <osmocom/core/gsmtap.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/abis.h>
#include <osmo-bts/bts.h>
@@ -284,6 +285,19 @@ int bts_main(int argc, char **argv)
exit(1);
}
+ if (!phy_link_by_num(0)) {
+ fprintf(stderr, "You need to configure at last phy0\n");
+ exit(1);
+ }
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (!trx->role_bts.l1h) {
+ fprintf(stderr, "TRX %u has no associated PHY instance\n",
+ trx->nr);
+ exit(1);
+ }
+ }
+
write_pid_file("osmo-bts");
bts_controlif_setup(bts);
@@ -317,6 +331,12 @@ int bts_main(int argc, char **argv)
exit(2);
}
+ rc = phy_links_open();
+ if (rc < 0) {
+ fprintf(stderr, "unable ot open PHY link(s)\n");
+ exit(2);
+ }
+
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
diff --git a/src/common/phy_link.c b/src/common/phy_link.c
new file mode 100644
index 0000000..0f24b51
--- /dev/null
+++ b/src/common/phy_link.c
@@ -0,0 +1,159 @@
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+
+#include <osmo-bts/bts.h>
+#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
+#include <osmo-bts/oml.h>
+#include <osmo-bts/logging.h>
+
+static LLIST_HEAD(g_phy_links);
+
+struct phy_link *phy_link_by_num(int num)
+{
+ struct phy_link *plink;
+
+ llist_for_each_entry(plink, &g_phy_links, list) {
+ if (plink->num == num)
+ return plink;
+ }
+
+ return NULL;
+}
+
+struct phy_link *phy_link_create(void *ctx, int num)
+{
+ struct phy_link *plink;
+
+ if (phy_link_by_num(num))
+ return NULL;
+
+ plink = talloc_zero(ctx, struct phy_link);
+ plink->num = num;
+ plink->state = PHY_LINK_SHUTDOWN;
+ INIT_LLIST_HEAD(&plink->instances);
+ llist_add_tail(&plink->list, &g_phy_links);
+
+ bts_model_phy_link_set_defaults(plink);
+
+ return plink;
+}
+
+const struct value_string phy_link_state_vals[] = {
+ { PHY_LINK_SHUTDOWN, "shutdown" },
+ { PHY_LINK_CONNECTING, "connectiong" },
+ { PHY_LINK_CONNECTED, "connected" },
+ { 0, NULL }
+};
+
+void phy_link_state_set(struct phy_link *plink, enum phy_link_state state)
+{
+ struct phy_instance *pinst;
+
+ LOGP(DL1C, LOGL_INFO, "PHY link state change %s -> %s\n",
+ get_value_string(phy_link_state_vals, plink->state),
+ get_value_string(phy_link_state_vals, state));
+
+ /* notify all TRX associated with this phy */
+ llist_for_each_entry(pinst, &plink->instances, list) {
+ struct gsm_bts_trx *trx = pinst->trx;
+ if (!trx)
+ continue;
+
+ switch (state) {
+ case PHY_LINK_CONNECTED:
+ LOGP(DL1C, LOGL_INFO, "trx_set_avail(1)\n");
+ trx_set_available(trx, 1);
+ break;
+ default:
+ LOGP(DL1C, LOGL_INFO, "trx_set_avail(0)\n");
+ trx_set_available(trx, 0);
+ break;
+ }
+ }
+
+ plink->state = state;
+}
+
+struct phy_instance *phy_instance_by_num(struct phy_link *plink, int num)
+{
+ struct phy_instance *pinst;
+
+ llist_for_each_entry(pinst, &plink->instances, list) {
+ if (pinst->num == num)
+ return pinst;
+ }
+ return NULL;
+}
+
+struct phy_instance *phy_instance_create(struct phy_link *plink, int num)
+{
+ struct phy_instance *pinst;
+
+ if (phy_instance_by_num(plink, num))
+ return NULL;
+
+ pinst = talloc_zero(plink, struct phy_instance);
+ pinst->num = num;
+ pinst->phy_link = plink;
+ llist_add_tail(&pinst->list, &plink->instances);
+
+ bts_model_phy_instance_set_defaults(pinst);
+
+ return pinst;
+}
+
+void phy_instance_link_to_trx(struct phy_instance *pinst, struct gsm_bts_trx *trx)
+{
+ trx->role_bts.l1h = pinst;
+ pinst->trx = trx;
+}
+
+void phy_instance_destroy(struct phy_instance *pinst)
+{
+ /* remove from list of instances in the link */
+ llist_del(&pinst->list);
+
+ /* remove reverse link from TRX */
+ OSMO_ASSERT(pinst->trx->role_bts.l1h == pinst);
+ pinst->trx->role_bts.l1h = NULL;
+ pinst->trx = NULL;
+
+ talloc_free(pinst);
+}
+
+void phy_link_destroy(struct phy_link *plink)
+{
+ struct phy_instance *pinst, *pinst2;
+
+ llist_for_each_entry_safe(pinst, pinst2, &plink->instances, list)
+ phy_instance_destroy(pinst);
+
+ talloc_free(plink);
+}
+
+int phy_links_open(void)
+{
+ struct phy_link *plink;
+
+ llist_for_each_entry(plink, &g_phy_links, list) {
+ int rc;
+
+ rc = bts_model_phy_link_open(plink);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+const char *phy_instance_name(struct phy_instance *pinst)
+{
+ static char buf[32];
+
+ snprintf(buf, sizeof(buf), "phy%u.%u", pinst->phy_link->num,
+ pinst->num);
+ return buf;
+}
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 64d89ac..de09fbf 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -134,11 +134,13 @@ const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX] = {
* init / exit
*/
-int trx_sched_init(struct l1sched_trx *l1t)
+int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx)
{
uint8_t tn;
int i;
+ l1t->trx = trx;
+
LOGP(DL1C, LOGL_NOTICE, "Init scheduler for trx=%u\n", l1t->trx->nr);
for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
@@ -191,7 +193,7 @@ void trx_sched_exit(struct l1sched_trx *l1t)
void trx_sched_reset(struct l1sched_trx *l1t)
{
trx_sched_exit(l1t);
- trx_sched_init(l1t);
+ trx_sched_init(l1t, l1t->trx);
}
struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn,
diff --git a/src/common/vty.c b/src/common/vty.c
index 4fd65d0..94ccdbe 100644
--- a/src/common/vty.c
+++ b/src/common/vty.c
@@ -40,6 +40,7 @@
#include <osmo-bts/logging.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
#include <osmo-bts/abis.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/rsl.h>
@@ -53,6 +54,13 @@
int bts_vty_go_parent(struct vty *vty)
{
switch (vty->node) {
+ case PHY_INST_NODE:
+ vty->node = PHY_NODE;
+ {
+ struct phy_instance *pinst = vty->index;
+ vty->index = pinst->phy_link;
+ }
+ break;
case TRX_NODE:
vty->node = BTS_NODE;
{
@@ -60,6 +68,7 @@ int bts_vty_go_parent(struct vty *vty)
vty->index = trx->bts;
}
break;
+ case PHY_NODE:
default:
vty->node = CONFIG_NODE;
}
@@ -71,6 +80,8 @@ int bts_vty_is_config_node(struct vty *vty, int node)
switch (node) {
case TRX_NODE:
case BTS_NODE:
+ case PHY_NODE:
+ case PHY_INST_NODE:
return 1;
default:
return 0;
@@ -81,6 +92,17 @@ gDEFUN(ournode_exit, ournode_exit_cmd, "exit",
"Exit current node, go down to provious node")
{
switch (vty->node) {
+ case PHY_INST_NODE:
+ vty->node = PHY_NODE;
+ {
+ struct phy_instance *pinst = vty->index;
+ vty->index = pinst->phy_link;
+ }
+ break;
+ case PHY_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
case TRX_NODE:
vty->node = BTS_NODE;
{
@@ -141,6 +163,7 @@ static struct cmd_node trx_node = {
1,
};
+
DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
"trx <0-254>",
"Select a TRX to configure\n" "TRX number\n")
@@ -151,7 +174,7 @@ DEFUN(cfg_bts_trx, cfg_bts_trx_cmd,
trx = gsm_bts_trx_num(bts, trx_nr);
if (!trx) {
- vty_out(vty, "Unknown TRX %u. Aavialable TRX are: 0..%d%s",
+ vty_out(vty, "Unknown TRX %u. Aavialable TRX are: 0..%u%s",
trx_nr, bts->num_trx - 1, VTY_NEWLINE);
return CMD_WARNING;
}
@@ -232,6 +255,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
llist_for_each_entry(trx, &bts->trx_list, list) {
struct trx_power_params *tpp = &trx->power_params;
+ struct phy_instance *pinst = trx_phy_instance(trx);
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
if (trx->power_params.user_gain_mdB)
@@ -246,6 +270,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " ms-power-control %s%s",
trx->ms_power_control == 0 ? "dsp" : "osmo",
VTY_NEWLINE);
+ vty_out(vty, " phy %u instance %u%s", pinst->phy_link->num,
+ pinst->num, VTY_NEWLINE);
bts_model_config_write_trx(vty, trx);
}
@@ -262,6 +288,35 @@ static int config_write_bts(struct vty *vty)
return CMD_SUCCESS;
}
+static void config_write_phy_single(struct vty *vty, struct phy_link *plink)
+{
+ int i;
+
+ vty_out(vty, "phy %u%s", plink->num, VTY_NEWLINE);
+ bts_model_config_write_phy(vty, plink);
+
+ for (i = 0; i < 255; i++) {
+ struct phy_instance *pinst = phy_instance_by_num(plink, i);
+ if (!pinst)
+ break;
+ vty_out(vty, " instance %u%s", pinst->num, VTY_NEWLINE);
+ }
+}
+
+static int config_write_phy(struct vty *vty)
+{
+ int i;
+
+ for (i = 0; i < 255; i++) {
+ struct phy_link *plink = phy_link_by_num(i);
+ if (!plink)
+ break;
+ config_write_phy_single(vty, plink);
+ }
+
+ return CMD_SUCCESS;
+}
+
static int config_write_dummy(struct vty *vty)
{
return CMD_SUCCESS;
@@ -532,6 +587,33 @@ DEFUN(cfg_trx_ms_power_control, cfg_trx_ms_power_control_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_trx_phy, cfg_trx_phy_cmd,
+ "phy <0-255> instance <0-255>",
+ "Configure PHY Link+Instance for this TRX\n"
+ "PHY Link number\n" "PHY instance\n" "PHY Instance number")
+{
+ struct gsm_bts_trx *trx = vty->index;
+ struct phy_link *plink = phy_link_by_num(atoi(argv[0]));
+ struct phy_instance *pinst;
+
+ if (!plink) {
+ vty_out(vty, "phy%s does not exist%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ pinst = phy_instance_by_num(plink, atoi(argv[1]));
+ if (!pinst) {
+ vty_out(vty, "phy%s instance %s does not exit%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ trx->role_bts.l1h = pinst;
+ pinst->trx = trx;
+
+ return CMD_SUCCESS;
+}
/* ======================================================================
* SHOW
@@ -702,6 +784,106 @@ DEFUN(cfg_trx_no_gsmtap_sapi, cfg_trx_no_gsmtap_sapi_cmd,
return CMD_SUCCESS;
}
+static struct cmd_node phy_node = {
+ PHY_NODE,
+ "%s(phy)#",
+ 1,
+};
+
+static struct cmd_node phy_inst_node = {
+ PHY_INST_NODE,
+ "%s(phy-inst)#",
+ 1,
+};
+
+DEFUN(cfg_phy, cfg_phy_cmd,
+ "phy <0-255>",
+ "Select a PHY to configure\n" "PHY number\n")
+{
+ int phy_nr = atoi(argv[0]);
+ struct phy_link *plink;
+
+ plink = phy_link_by_num(phy_nr);
+ if (!plink)
+ plink = phy_link_create(tall_bts_ctx, phy_nr);
+ if (!plink)
+ return CMD_WARNING;
+
+ vty->index = plink;
+ vty->index_sub = &plink->description;
+ vty->node = PHY_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_inst, cfg_phy_inst_cmd,
+ "instance <0-255>",
+ "Select a PHY instance to configure\n" "PHY Instance number\n")
+{
+ int inst_nr = atoi(argv[0]);
+ struct phy_link *plink = vty->index;
+ struct phy_instance *pinst;
+
+ pinst = phy_instance_by_num(plink, inst_nr);
+ if (!pinst) {
+ pinst = phy_instance_create(plink, inst_nr);
+ if (!pinst) {
+ vty_out(vty, "Unable to create phy%u instance %u%s",
+ plink->num, inst_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ vty->index = pinst;
+ vty->index_sub = &pinst->description;
+ vty->node = PHY_INST_NODE;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_no_inst, cfg_phy_no_inst_cmd,
+ "no instance <0-255>"
+ NO_STR "Select a PHY instance to remove\n", "PHY Instance number\n")
+{
+ int inst_nr = atoi(argv[0]);
+ struct phy_link *plink = vty->index;
+ struct phy_instance *pinst;
+
+ pinst = phy_instance_by_num(plink, inst_nr);
+ if (!pinst) {
+ vty_out(vty, "No such instance %u%s", inst_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ phy_instance_destroy(pinst);
+
+ return CMD_SUCCESS;
+}
+
+#if 0
+DEFUN(cfg_phy_type, cfg_phy_type_cmd,
+ "type (sysmobts|osmo-trx|virtual)",
+ "configure the type of the PHY\n"
+ "sysmocom sysmoBTS PHY\n"
+ "OsmoTRX based PHY\n"
+ "Virtual PHY (GSMTAP based)\n")
+{
+ struct phy_link *plink = vty->index;
+
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Cannot change type of active PHY%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[0], "sysmobts"))
+ plink->type = PHY_LINK_T_SYSMOBTS;
+ else if (!strcmp(argv[0], "osmo-trx"))
+ plink->type = PHY_LINK_T_OSMOTRX;
+ else if (!strcmp(argv[0], "virtual"))
+ plink->type = PHY_LINK_T_VIRTUAL;
+}
+#endif
+
DEFUN(bts_t_t_l_jitter_buf,
bts_t_t_l_jitter_buf_cmd,
"bts <0-0> trx <0-0> ts <0-7> lchan <0-1> rtp jitter-buffer <0-10000>",
@@ -813,10 +995,20 @@ int bts_vty_init(struct gsm_bts *bts, const struct log_info *cat)
install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd);
install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd);
install_element(TRX_NODE, &cfg_trx_ms_power_control_cmd);
+ install_element(TRX_NODE, &cfg_trx_phy_cmd);
install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd);
install_element(ENABLE_NODE, &bts_t_t_l_loopback_cmd);
install_element(ENABLE_NODE, &no_bts_t_t_l_loopback_cmd);
+ install_element(CONFIG_NODE, &cfg_phy_cmd);
+ install_node(&phy_node, config_write_phy);
+ install_default(PHY_NODE);
+ install_element(PHY_NODE, &cfg_phy_inst_cmd);
+ install_element(PHY_NODE, &cfg_phy_no_inst_cmd);
+
+ install_node(&phy_inst_node, config_write_dummy);
+ install_default(PHY_INST_NODE);
+
return 0;
}
diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c
index db6e032..3215aa1 100644
--- a/src/osmo-bts-octphy/l1_if.c
+++ b/src/osmo-bts-octphy/l1_if.c
@@ -38,6 +38,7 @@
#include <osmocom/core/socket.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/bts_model.h>
#include <osmo-bts/oml.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/l1sap.h>
@@ -109,6 +110,17 @@ osmocom_to_octphy_band(enum gsm_band osmo_band, unsigned int arfcn)
}
};
+struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id)
+{
+ struct phy_instance *pinst;
+
+ pinst = phy_instance_by_num(fl1h->phy_link, trx_id);
+ if (!pinst)
+ return NULL;
+
+ return pinst->trx;
+}
+
struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx,
tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id)
{
@@ -282,10 +294,9 @@ int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
}
/* For OctPHY, this only about sending state changes to BSC */
-int l1if_activate_rf(struct octphy_hdl *fl1h, int on)
+int l1if_activate_rf(struct gsm_bts_trx *trx, int on)
{
int i;
- struct gsm_bts_trx *trx = fl1h->priv;
if (on) {
/* signal availability */
oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OK);
@@ -422,7 +433,8 @@ static void empty_req_from_rts_ind(tOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_E
static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
struct osmo_phsap_prim *l1sap)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *l1msg = l1p_msgb_alloc();
uint32_t u32Fn;
uint8_t u8Tn, subCh, sapi = 0;
@@ -489,7 +501,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
l1if_fill_msg_hdr(&data_req->Header, l1msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID);
- data_req->TrxId.byTrxId = trx->nr;
+ data_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
data_req->LchId.byTimeslotNb = u8Tn;
data_req->LchId.bySAPI = sapi;
data_req->LchId.bySubChannelNb = subCh;
@@ -508,7 +520,7 @@ static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
l1if_fill_msg_hdr(&empty_frame_req->Header, l1msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CID);
- empty_frame_req->TrxId.byTrxId = trx->nr;
+ empty_frame_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
empty_frame_req->LchId.byTimeslotNb = u8Tn;
empty_frame_req->LchId.bySAPI = sapi;
empty_frame_req->LchId.bySubChannelNb = subCh;
@@ -527,7 +539,8 @@ done:
static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
struct osmo_phsap_prim *l1sap)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct gsm_lchan *lchan;
uint32_t u32Fn;
uint8_t u8Tn, subCh, sapi, ss;
@@ -565,7 +578,7 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
l1if_fill_msg_hdr(&data_req->Header, nmsg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_DATA_CID);
- data_req->TrxId.byTrxId = trx->nr;
+ data_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
data_req->LchId.byTimeslotNb = u8Tn;
data_req->LchId.bySAPI = sapi;
data_req->LchId.bySubChannelNb = subCh;
@@ -590,7 +603,7 @@ static int ph_tch_req(struct gsm_bts_trx *trx, struct msgb *msg,
l1if_fill_msg_hdr(&empty_frame_req->Header, nmsg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_REQUEST_LOGICAL_CHANNEL_EMPTY_FRAME_CID);
- empty_frame_req->TrxId.byTrxId = trx->nr;
+ empty_frame_req->TrxId.byTrxId = pinst->u.octphy.trx_id;
empty_frame_req->LchId.byTimeslotNb = u8Tn;
empty_frame_req->LchId.bySAPI = sapi;
empty_frame_req->LchId.bySubChannelNb = subCh;
@@ -686,32 +699,78 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
return rc;
}
+static int trx_close_all_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
+{
+ tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *car =
+ (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *) resp->l2h;
+
+ /* in a completion call-back, we take msgb ownership and must
+ * release it before returning */
+
+ mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP_SWAP(car);
+
+ /* we now know that the PHY link is connected */
+ phy_link_state_set(fl1->phy_link, PHY_LINK_CONNECTED);
+
+ msgb_free(resp);
+
+ return 0;
+}
+
+static int phy_link_trx_close_all(struct phy_link *plink)
+{
+ struct octphy_hdl *fl1h = plink->u.octphy.hdl;
+ struct msgb *msg = l1p_msgb_alloc();
+ tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *cac;
+
+ cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *)
+ msgb_put(msg, sizeof(*cac));
+ l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
+ cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID);
+
+ mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD_SWAP(cac);
+
+ return l1if_req_compl(fl1h, msg, trx_close_all_cb, NULL);
+}
+
+int bts_model_phy_link_open(struct phy_link *plink)
+{
+ if (plink->u.octphy.hdl)
+ l1if_close(plink->u.octphy.hdl);
+
+ phy_link_state_set(plink, PHY_LINK_CONNECTING);
+
+ plink->u.octphy.hdl = l1if_open(plink);
+ if (!plink->u.octphy.hdl) {
+ phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
+ return -1;
+ }
+
+ /* do we need to iterate over the list of instances and do some
+ * instance-specific initialization? */
+
+ /* close all TRXs that might still exist in this link from
+ * previous execitions / sessions */
+ phy_link_trx_close_all(plink);
+
+ /* in the call-back to the above we will set the link state to
+ * connected */
+
+ return 0;
+}
+
int bts_model_init(struct gsm_bts *bts)
{
struct gsm_bts_role_bts *btsb;
- struct octphy_hdl *fl1h;
LOGP(DL1C, LOGL_NOTICE, "model_init()\n");
btsb = bts_role_bts(bts);
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
- fl1h = talloc_zero(bts, struct octphy_hdl);
- if (!fl1h)
- return -ENOMEM;
-
- INIT_LLIST_HEAD(&fl1h->wlc_list);
- INIT_LLIST_HEAD(&fl1h->wlc_postponed);
- fl1h->priv = bts->c0;
- bts->c0->role_bts.l1h = fl1h;
/* FIXME: what is the nominal transmit power of the PHY/board? */
bts->c0->nominal_power = 15;
- /* configure some reasonable defaults, to be overridden by VTY */
- fl1h->config.rf_port_index = 0;
- fl1h->config.rx_gain_db = 70;
- fl1h->config.tx_atten_db = 0;
-
bts_model_vty_init(bts);
return 0;
@@ -750,23 +809,15 @@ static void dump_meas_res(int ll, tOCTVC1_GSM_MEASUREMENT_INFO * m)
static int handle_mph_time_ind(struct octphy_hdl *fl1, uint8_t trx_id, uint32_t fn)
{
- struct gsm_bts_trx *trx = fl1->priv;
- struct gsm_bts *bts = trx->bts;
+ struct gsm_bts_trx *trx = trx_by_l1h(fl1, trx_id);
struct osmo_phsap_prim l1sap;
/* increment the primitive count for the alive timer */
fl1->alive_prim_cnt++;
/* ignore every time indication, except for c0 */
- if (trx != bts->c0)
- return 0;
-
- if (trx_id != trx->nr) {
- LOGP(DL1C, LOGL_FATAL,
- "TRX id %d from response does not match the L1 context trx %d\n",
- trx_id, trx->nr);
+ if (trx != trx->bts->c0)
return 0;
- }
memset(&l1sap, 0, sizeof(l1sap));
osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_MPH_INFO,
@@ -783,7 +834,7 @@ static int handle_ph_readytosend_ind(struct octphy_hdl *fl1,
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_READY_TO_SEND_INDICATION_EVT *evt,
struct msgb *l1p_msg)
{
- struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts_trx *trx = trx_by_l1h(fl1, evt->TrxId.byTrxId);
struct gsm_bts *bts = trx->bts;
struct osmo_phsap_prim *l1sap;
struct gsm_time g_time;
@@ -908,7 +959,7 @@ static int handle_ph_data_ind(struct octphy_hdl *fl1,
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *data_ind,
struct msgb *l1p_msg)
{
- struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts_trx *trx = trx_by_l1h(fl1, data_ind->TrxId.byTrxId);
uint8_t chan_nr, link_id;
struct osmo_phsap_prim *l1sap;
uint32_t fn;
@@ -992,7 +1043,7 @@ static int handle_ph_rach_ind(struct octphy_hdl *fl1,
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_RACH_INDICATION_EVT *ra_ind,
struct msgb *l1p_msg)
{
- struct gsm_bts_trx *trx = fl1->priv;
+ struct gsm_bts_trx *trx = trx_by_l1h(fl1, ra_ind->TrxId.byTrxId);
struct gsm_bts *bts = trx->bts;
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
struct gsm_lchan *lchan;
@@ -1131,7 +1182,7 @@ static int rx_octvc1_resp(struct msgb *msg, uint32_t msg_id, uint32_t trans_id)
if (wlc->cb) {
/* call-back function must take msgb
* ownership. */
- rc = wlc->cb(fl1h->priv, msg, wlc->cb_data);
+ rc = wlc->cb(fl1h, msg, wlc->cb_data);
} else {
rc = 0;
msgb_free(msg);
@@ -1485,6 +1536,18 @@ static int rx_octphy_msg(struct msgb *msg)
return rc;
}
+void bts_model_phy_link_set_defaults(struct phy_link *plink)
+{
+ /* configure some reasonable defaults, to be overridden by VTY */
+ plink->u.octphy.rf_port_index = 0;
+ plink->u.octphy.rx_gain_db = 70;
+ plink->u.octphy.tx_atten_db = 0;
+}
+
+void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
+{
+}
+
/***********************************************************************
* octphy socket / main loop integration
***********************************************************************/
@@ -1534,15 +1597,25 @@ static int octphy_write_cb(struct osmo_fd *fd, struct msgb *msg)
return rc;
}
-int l1if_open(struct octphy_hdl *fl1h)
+struct octphy_hdl *l1if_open(struct phy_link *plink)
{
+ struct octphy_hdl *fl1h;
struct ifreq ifr;
int sfd, rc;
- char *phy_dev = fl1h->netdev_name;
+ char *phy_dev = plink->u.octphy.netdev_name;
+
+ fl1h = talloc_zero(plink, struct octphy_hdl);
+ if (!fl1h)
+ return NULL;
+
+ INIT_LLIST_HEAD(&fl1h->wlc_list);
+ INIT_LLIST_HEAD(&fl1h->wlc_postponed);
+ fl1h->phy_link = plink;
if (!phy_dev) {
LOGP(DL1C, LOGL_ERROR, "You have to specify a phy-netdev\n");
- return -EINVAL;
+ talloc_free(fl1h);
+ return NULL;
}
LOGP(DL1C, LOGL_NOTICE, "Opening L1 interface for OctPHY (%s)\n",
@@ -1553,7 +1626,8 @@ int l1if_open(struct octphy_hdl *fl1h)
if (sfd < 0) {
LOGP(DL1C, LOGL_FATAL, "Error opening PHY socket: %s\n",
strerror(errno));
- return -EIO;
+ talloc_free(fl1h);
+ return NULL;
}
/* resolve the string device name to an ifindex */
@@ -1564,18 +1638,21 @@ int l1if_open(struct octphy_hdl *fl1h)
LOGP(DL1C, LOGL_FATAL, "Error using network device %s: %s\n",
phy_dev, strerror(errno));
close(sfd);
- return -EIO;
+ talloc_free(fl1h);
+ return NULL;
}
fl1h->session_id = rand();
- /* set fl1h->phy_addr, which we use as sendto() destionation */
+ /* set fl1h->phy_addr, which we use as sendto() destination */
fl1h->phy_addr.sll_family = AF_PACKET;
fl1h->phy_addr.sll_protocol = htons(cOCTPKT_HDR_ETHERTYPE);
fl1h->phy_addr.sll_ifindex = ifr.ifr_ifindex;
fl1h->phy_addr.sll_hatype = ARPHRD_ETHER;
- fl1h->phy_addr.sll_halen = 6;
- /* sll_addr is filled by bts_model_vty code */
+ fl1h->phy_addr.sll_halen = ETH_ALEN;
+ /* plink->phy_addr.sll_addr is filled by bts_model_vty code */
+ memcpy(fl1h->phy_addr.sll_addr, plink->u.octphy.phy_addr.sll_addr,
+ ETH_ALEN);
/* Write queue / osmo_fd registration */
osmo_wqueue_init(&fl1h->phy_wq, 10);
@@ -1588,10 +1665,11 @@ int l1if_open(struct octphy_hdl *fl1h)
rc = osmo_fd_register(&fl1h->phy_wq.bfd);
if (rc < 0) {
close(sfd);
- return -EIO;
+ talloc_free(fl1h);
+ return NULL;
}
- return 0;
+ return fl1h;
}
int l1if_close(struct octphy_hdl *fl1h)
diff --git a/src/osmo-bts-octphy/l1_if.h b/src/osmo-bts-octphy/l1_if.h
index 4277865..2dee178 100644
--- a/src/osmo-bts-octphy/l1_if.h
+++ b/src/osmo-bts-octphy/l1_if.h
@@ -13,16 +13,16 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
#include <octphy/octvc1/gsm/octvc1_gsm_api.h>
struct octphy_hdl {
+ /* MAC address of the PHY */
+ struct sockaddr_ll phy_addr;
+
/* packet socket to talk with PHY */
struct osmo_wqueue phy_wq;
- /* MAC address of th PHY */
- struct sockaddr_ll phy_addr;
- /* Network device name */
- char *netdev_name;
/* address parameters of the PHY */
uint32_t session_id;
@@ -33,12 +33,6 @@ struct octphy_hdl {
uint32_t clkmgr_state;
struct {
- uint32_t rf_port_index;
- uint32_t rx_gain_db;
- uint32_t tx_atten_db;
- } config;
-
- struct {
struct {
char *name;
char *description;
@@ -72,8 +66,8 @@ struct octphy_hdl {
struct llist_head wlc_postponed;
int wlc_postponed_len;
- /* private pointer, points back to TRX */
- void *priv;
+ /* back pointer to the PHY link */
+ struct phy_link *phy_link;
struct osmo_timer_list alive_timer;
uint32_t alive_prim_cnt;
@@ -82,15 +76,10 @@ struct octphy_hdl {
int opened;
};
-static inline struct octphy_hdl *trx_octphy_hdl(struct gsm_bts_trx *trx)
-{
- return trx->role_bts.l1h;
-}
-
void l1if_fill_msg_hdr(tOCTVC1_MSG_HEADER *mh, struct msgb *msg,
struct octphy_hdl *fl1h, uint32_t msg_type, uint32_t api_cmd);
-typedef int l1if_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg, void *data);
+typedef int l1if_compl_cb(struct octphy_hdl *fl1, struct msgb *l1_msg, void *data);
/* send a request primitive to the L1 and schedule completion call-back */
int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
@@ -100,19 +89,21 @@ int l1if_req_compl(struct octphy_hdl *fl1h, struct msgb *msg,
struct gsm_lchan *get_lchan_by_lchid(struct gsm_bts_trx *trx,
tOCTVC1_GSM_LOGICAL_CHANNEL_ID *lch_id);
-int l1if_open(struct octphy_hdl *fl1h);
+struct octphy_hdl *l1if_open(struct phy_link *plink);
int l1if_close(struct octphy_hdl *hdl);
int l1if_trx_open(struct gsm_bts_trx *trx);
int l1if_trx_close_all(struct gsm_bts *bts);
int l1if_enable_events(struct gsm_bts_trx *trx);
-int l1if_activate_rf(struct octphy_hdl *fl1h, int on);
+int l1if_activate_rf(struct gsm_bts_trx *trx, int on);
int l1if_tch_rx(struct gsm_bts_trx *trx, uint8_t chan_nr,
tOCTVC1_GSM_MSG_TRX_LOGICAL_CHANNEL_DATA_INDICATION_EVT *
data_ind);
+struct gsm_bts_trx *trx_by_l1h(struct octphy_hdl *fl1h, unsigned int trx_id);
+
struct msgb *l1p_msgb_alloc(void);
/* tch.c */
diff --git a/src/osmo-bts-octphy/l1_oml.c b/src/osmo-bts-octphy/l1_oml.c
index 318c384..c50f1d6 100644
--- a/src/osmo-bts-octphy/l1_oml.c
+++ b/src/osmo-bts-octphy/l1_oml.c
@@ -348,10 +348,11 @@ static void sapi_clear_queue(struct llist_head *queue)
}
}
-static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int lchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *ar =
(tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h;
+ struct gsm_bts_trx *trx;
struct gsm_lchan *lchan;
uint8_t sapi;
uint8_t direction;
@@ -361,7 +362,7 @@ static int lchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
* release it before returning */
mOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ar);
- OSMO_ASSERT(ar->TrxId.byTrxId == trx->nr);
+ trx = trx_by_l1h(fl1, ar->TrxId.byTrxId);
lchan = get_lchan_by_lchid(trx, &ar->LchId);
sapi = ar->LchId.bySAPI;
@@ -411,7 +412,8 @@ err:
static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CMD *lac;
@@ -420,7 +422,7 @@ static int mph_send_activate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
l1if_fill_msg_hdr(&lac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_ACTIVATE_LOGICAL_CHANNEL_CID);
- lac->TrxId.byTrxId = lchan->ts->trx->nr;
+ lac->TrxId.byTrxId = pinst->u.octphy.trx_id;
lac->LchId.byTimeslotNb = lchan->ts->nr;
lac->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan);
lac->LchId.bySAPI = cmd->sapi;
@@ -451,10 +453,11 @@ static tOCTVC1_GSM_CIPHERING_ID_ENUM rsl2l1_ciph[] = {
[4] = cOCTVC1_GSM_CIPHERING_ID_ENUM_A5_3
};
-static int set_ciph_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int set_ciph_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *pcr =
(tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_RSP *) resp->l2h;
+ struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_lchan *lchan;
@@ -470,6 +473,7 @@ static int set_ciph_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
exit(-1);
}
+ trx = trx_by_l1h(fl1, pcr->TrxId.byTrxId);
OSMO_ASSERT(pcr->TrxId.byTrxId == trx->nr);
ts = &trx->ts[pcr->PchId.byTimeslotNb];
/* for some strange reason the response does not tell which
@@ -508,8 +512,8 @@ err:
static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
{
- struct gsm_bts_trx *trx = lchan->ts->trx;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CMD *pcc;
@@ -518,6 +522,7 @@ static int mph_send_config_ciphering(struct gsm_lchan *lchan, struct sapi_cmd *c
l1if_fill_msg_hdr(&pcc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_MODIFY_PHYSICAL_CHANNEL_CIPHERING_CID);
+ pcc->TrxId.byTrxId = pinst->u.octphy.trx_id;
pcc->PchId.byTimeslotNb = lchan->ts->nr;
pcc->ulSubchannelNb = lchan_to_GsmL1_SubCh_t(lchan);
pcc->ulDirection = cmd->dir;
@@ -627,7 +632,8 @@ static int check_sapi_release(struct gsm_lchan *lchan, int sapi, int dir)
static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
int i, res;
@@ -654,10 +660,11 @@ static int lchan_deactivate_sapis(struct gsm_lchan *lchan)
return res;
}
-static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int lchan_deact_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *ldr =
(tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP *) resp->l2h;
+ struct gsm_bts_trx *trx;
struct gsm_lchan *lchan;
struct sapi_cmd *cmd;
uint8_t status;
@@ -666,7 +673,7 @@ static int lchan_deact_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void
* release it before returning */
mOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_RSP_SWAP(ldr);
- OSMO_ASSERT(ldr->TrxId.byTrxId == trx->nr);
+ trx = trx_by_l1h(fl1, ldr->TrxId.byTrxId);
lchan = get_lchan_by_lchid(trx, &ldr->LchId);
@@ -725,7 +732,8 @@ err:
static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CMD *ldc;
@@ -734,6 +742,7 @@ static int mph_send_deactivate_req(struct gsm_lchan *lchan, struct sapi_cmd *cmd
l1if_fill_msg_hdr(&ldc->Header, msg, fl1h,cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_DEACTIVATE_LOGICAL_CHANNEL_CID);
+ ldc->TrxId.byTrxId = pinst->u.octphy.trx_id;
ldc->LchId.byTimeslotNb = lchan->ts->nr;
ldc->LchId.bySubChannelNb = lchan_to_GsmL1_SubCh_t(lchan);
ldc->LchId.byDirection = cmd->dir;
@@ -1031,7 +1040,8 @@ static void enqueue_sapi_act_cmd(struct gsm_lchan *lchan, int sapi, int dir)
int lchan_activate(struct gsm_lchan *lchan)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(lchan->ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(lchan->ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
const struct lchan_sapis *s4l = &sapis_for_lchan[lchan->type];
unsigned int i;
@@ -1069,7 +1079,7 @@ int l1if_rsl_chan_act(struct gsm_lchan *lchan)
return 0;
}
-static int enable_events_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int enable_events_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_RSP *mser =
(tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_RSP *) resp->l2h;
@@ -1088,7 +1098,8 @@ static int enable_events_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, vo
int l1if_enable_events(struct gsm_bts_trx *trx)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_MAIN_MSG_API_SYSTEM_MODIFY_SESSION_EVT_CMD *mse;
@@ -1112,9 +1123,8 @@ int l1if_enable_events(struct gsm_bts_trx *trx)
dst = talloc_strdup(ctx, (const char *) src); \
} while (0)
-static int app_info_sys_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int app_info_sys_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
{
- struct octphy_hdl *fl1h = resp->dst;
tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *aisr =
(tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_RSP *) resp->l2h;
@@ -1136,7 +1146,8 @@ static int app_info_sys_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, voi
int l1if_check_app_sys_version(struct gsm_bts_trx *trx)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_MAIN_MSG_APPLICATION_INFO_SYSTEM_CMD *ais;
@@ -1152,9 +1163,8 @@ int l1if_check_app_sys_version(struct gsm_bts_trx *trx)
return l1if_req_compl(fl1h, msg, app_info_sys_compl_cb, 0);
}
-static int app_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int app_info_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
{
- struct octphy_hdl *fl1h = resp->dst;
tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *air =
(tOCTVC1_MAIN_MSG_APPLICATION_INFO_RSP *) resp->l2h;
@@ -1178,7 +1188,8 @@ static int app_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
int l1if_check_app_version(struct gsm_bts_trx *trx)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_MAIN_MSG_APPLICATION_INFO_CMD *ai;
@@ -1193,9 +1204,50 @@ int l1if_check_app_version(struct gsm_bts_trx *trx)
return l1if_req_compl(fl1h, msg, app_info_compl_cb, 0);
}
+static int trx_close_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
+{
+ tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *car =
+ (tOCTVC1_GSM_MSG_TRX_CLOSE_RSP *) resp->l2h;
+
+ /* in a completion call-back, we take msgb ownership and must
+ * release it before returning */
+
+ mOCTVC1_GSM_MSG_TRX_CLOSE_RSP_SWAP(car);
+
+ LOGP(DL1C, LOGL_INFO, "Rx TRX-CLOSE.conf(%u)\n", car->TrxId.byTrxId);
+
+ msgb_free(resp);
+
+ return 0;
+}
+
+static int trx_close(struct gsm_bts_trx *trx)
+{
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct phy_link *plink = pinst->phy_link;
+ struct octphy_hdl *fl1h = plink->u.octphy.hdl;
+ struct msgb *msg = l1p_msgb_alloc();
+ tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *cac;
+
+ cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_CMD *)
+ msgb_put(msg, sizeof(*cac));
+ l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
+ cOCTVC1_GSM_MSG_TRX_CLOSE_CID);
+
+ cac->TrxId.byTrxId = pinst->u.octphy.trx_id;
+
+ LOGP(DL1C, LOGL_INFO, "Tx TRX-CLOSE.req(%u)\n", cac->TrxId.byTrxId);
+
+ mOCTVC1_GSM_MSG_TRX_CLOSE_CMD_SWAP(cac);
+
+ return l1if_req_compl(fl1h, msg, trx_close_cb, NULL);
+}
+
/* call-back once the TRX_OPEN_CID response arrives */
-static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int trx_open_compl_cb(struct octphy_hdl *fl1h, struct msgb *resp, void *data)
{
+ struct gsm_bts_trx *trx;
+
tOCTVC1_GSM_MSG_TRX_OPEN_RSP *or =
(tOCTVC1_GSM_MSG_TRX_OPEN_RSP *) resp->l2h;
@@ -1203,8 +1255,7 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
* release it before returning */
mOCTVC1_GSM_MSG_TRX_OPEN_RSP_SWAP(or);
-
- OSMO_ASSERT(or->TrxId.byTrxId == trx->nr);
+ trx = trx_by_l1h(fl1h, or->TrxId.byTrxId);
LOGP(DL1C, LOGL_INFO, "TRX-OPEN.resp(trx=%u) = %s\n",
trx->nr, octvc1_rc2string(or->Header.ulReturnCode));
@@ -1221,7 +1272,6 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
opstart_compl(&trx->mo);
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
octphy_hw_get_pcb_info(fl1h);
octphy_hw_get_rf_port_info(fl1h, 0);
octphy_hw_get_rf_ant_rx_config(fl1h, 0, 0);
@@ -1238,22 +1288,24 @@ static int trx_open_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *d
int l1if_trx_open(struct gsm_bts_trx *trx)
{
/* putting it all together */
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct phy_link *plink = pinst->phy_link;
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_GSM_MSG_TRX_OPEN_CMD *oc;
oc = (tOCTVC1_GSM_MSG_TRX_OPEN_CMD *) msgb_put(msg, sizeof(*oc));
l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_OPEN_CID);
- oc->ulRfPortIndex = fl1h->config.rf_port_index;
- oc->TrxId.byTrxId = trx->nr;
+ oc->ulRfPortIndex = plink->u.octphy.rf_port_index;
+ oc->TrxId.byTrxId = pinst->u.octphy.trx_id;
oc->Config.ulBand = osmocom_to_octphy_band(trx->bts->band, trx->arfcn);
oc->Config.usArfcn = trx->arfcn;
oc->Config.usTsc = trx->bts->bsic & 0x7;
oc->Config.usBcchArfcn = trx->bts->c0->arfcn;
- oc->RfConfig.ulRxGainDb = fl1h->config.rx_gain_db;
+ oc->RfConfig.ulRxGainDb = plink->u.octphy.rx_gain_db;
/* FIXME: compute this based on nominal transmit power, etc. */
- oc->RfConfig.ulTxAttndB = fl1h->config.tx_atten_db;
+ oc->RfConfig.ulTxAttndB = plink->u.octphy.tx_atten_db;
LOGP(DL1C, LOGL_INFO, "Tx TRX-OPEN.req(trx=%u, rf_port=%u, arfcn=%u, "
"tsc=%u, rx_gain=%u, tx_atten=%u)\n",
@@ -1266,38 +1318,6 @@ int l1if_trx_open(struct gsm_bts_trx *trx)
return l1if_req_compl(fl1h, msg, trx_open_compl_cb, NULL);
}
-static int trx_close_all_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
-{
- tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *car =
- (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP *) resp->l2h;
-
- /* in a completion call-back, we take msgb ownership and must
- * release it before returning */
-
- mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_RSP_SWAP(car);
-
- msgb_free(resp);
-
- return 0;
-}
-
-int l1if_trx_close_all(struct gsm_bts *bts)
-{
- struct octphy_hdl *fl1h = trx_octphy_hdl(bts->c0);
- struct msgb *msg = l1p_msgb_alloc();
- tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *cac;
-
- cac = (tOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD *)
- msgb_put(msg, sizeof(*cac));
- l1if_fill_msg_hdr(&cac->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
- cOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CID);
-
- mOCTVC1_GSM_MSG_TRX_CLOSE_ALL_CMD_SWAP(cac);
-
- return l1if_req_compl(fl1h, msg, trx_close_all_cb, NULL);
-}
-
-
uint32_t trx_get_hlayer1(struct gsm_bts_trx * trx)
{
return 0;
@@ -1313,8 +1333,6 @@ static int trx_init(struct gsm_bts_trx *trx)
/* return oml_mo_opstart_nack(&trx->mo, NM_NACK_CANT_PERFORM); */
}
- l1if_trx_close_all(trx->bts);
-
l1if_check_app_version(trx);
l1if_check_app_sys_version(trx);
@@ -1325,11 +1343,12 @@ static int trx_init(struct gsm_bts_trx *trx)
* PHYSICAL CHANNE ACTIVATION
***********************************************************************/
-static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int pchan_act_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *ar =
(tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP *) resp->l2h;
uint8_t ts_nr;
+ struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_abis_mo *mo;
@@ -1337,9 +1356,8 @@ static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
* release it before returning */
mOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_RSP_SWAP(ar);
+ trx = trx_by_l1h(fl1, ar->TrxId.byTrxId);
ts_nr = ar->PchId.byTimeslotNb;
-
- OSMO_ASSERT(ar->TrxId.byTrxId == trx->nr);
OSMO_ASSERT(ts_nr <= ARRAY_SIZE(trx->ts));
ts = &trx->ts[ts_nr];
@@ -1367,7 +1385,8 @@ static int pchan_act_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *
static int ts_connect(struct gsm_bts_trx_ts *ts)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(ts->trx);
+ struct octphy_hdl *fl1h = pinst->phy_link->u.octphy.hdl;
struct msgb *msg = l1p_msgb_alloc();
tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *oc =
(tOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CMD *) oc;
@@ -1376,7 +1395,7 @@ static int ts_connect(struct gsm_bts_trx_ts *ts)
l1if_fill_msg_hdr(&oc->Header, msg, fl1h, cOCTVC1_MSG_TYPE_COMMAND,
cOCTVC1_GSM_MSG_TRX_ACTIVATE_PHYSICAL_CHANNEL_CID);
- oc->TrxId.byTrxId = ts->trx->nr;
+ oc->TrxId.byTrxId = pinst->u.octphy.trx_id;
oc->PchId.byTimeslotNb = ts->nr;
oc->ulChannelType = pchan_to_logChComb[ts->pchan];
@@ -1430,8 +1449,7 @@ int bts_model_oml_estab(struct gsm_bts *bts)
int i;
for (i = 0; i < bts->num_trx; i++) {
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, i);
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
- l1if_activate_rf(fl1h, 1);
+ l1if_activate_rf(trx, 1);
}
return 0;
}
@@ -1447,14 +1465,13 @@ int bts_model_chg_adm_state(struct gsm_bts *bts, struct gsm_abis_mo *mo,
int bts_model_trx_deact_rf(struct gsm_bts_trx *trx)
{
- struct octphy_hdl *fl1 = trx_octphy_hdl(trx);
- return l1if_activate_rf(fl1, 0);
+ return l1if_activate_rf(trx, 0);
}
int bts_model_trx_close(struct gsm_bts_trx *trx)
{
/* FIXME: close only one TRX */
- return l1if_trx_close_all(trx->bts);
+ return trx_close(trx);
}
diff --git a/src/osmo-bts-octphy/main.c b/src/osmo-bts-octphy/main.c
index 1f516e4..0f4d0dd 100644
--- a/src/osmo-bts-octphy/main.c
+++ b/src/osmo-bts-octphy/main.c
@@ -52,10 +52,9 @@
extern int pcu_direct;
-static struct gsm_bts *bts;
-
int bts_model_print_help()
{
+ return 0;
}
int bts_model_handle_options(int argc, char **argv)
diff --git a/src/osmo-bts-octphy/octphy_hw_api.c b/src/osmo-bts-octphy/octphy_hw_api.c
index 5291742..ec7c4be 100644
--- a/src/osmo-bts-octphy/octphy_hw_api.c
+++ b/src/osmo-bts-octphy/octphy_hw_api.c
@@ -35,7 +35,7 @@
#include <octphy/octvc1/hw/octvc1_hw_api_swap.h>
/* Chapter 12.1 */
-static int get_pcb_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp, void *data)
+static int get_pcb_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp, void *data)
{
tOCTVC1_HW_MSG_PCB_INFO_RSP *pir =
(tOCTVC1_HW_MSG_PCB_INFO_RSP *) resp->l2h;
@@ -69,7 +69,7 @@ int octphy_hw_get_pcb_info(struct octphy_hdl *fl1h)
}
/* Chapter 12.9 */
-static int rf_port_info_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int rf_port_info_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_RF_PORT_INFO_RSP *pir =
@@ -114,7 +114,7 @@ static const struct value_string radio_std_vals[] = {
};
/* Chapter 12.10 */
-static int rf_port_stats_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int rf_port_stats_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_RF_PORT_STATS_RSP *psr =
@@ -167,7 +167,7 @@ static const struct value_string rx_gain_mode_vals[] = {
};
/* Chapter 12.13 */
-static int rf_ant_rx_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int rf_ant_rx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_RX_CONFIG_RSP *arc =
@@ -209,7 +209,7 @@ int octphy_hw_get_rf_ant_rx_config(struct octphy_hdl *fl1h, uint32_t port_idx,
}
/* Chapter 12.14 */
-static int rf_ant_tx_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int rf_ant_tx_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_RF_PORT_INFO_ANTENNA_TX_CONFIG_RSP *atc =
@@ -292,7 +292,7 @@ static const struct value_string clocksync_state_vals[] = {
};
/* Chapter 12.15 */
-static int get_clock_sync_compl_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int get_clock_sync_compl_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_INFO_RSP *cir =
@@ -326,7 +326,7 @@ int octphy_hw_get_clock_sync_info(struct octphy_hdl *fl1h)
}
/* Chapter 12.16 */
-static int get_clock_sync_stats_cb(struct gsm_bts_trx *trx, struct msgb *resp,
+static int get_clock_sync_stats_cb(struct octphy_hdl *fl1, struct msgb *resp,
void *data)
{
tOCTVC1_HW_MSG_CLOCK_SYNC_MGR_STATS_RSP *csr =
diff --git a/src/osmo-bts-octphy/octphy_vty.c b/src/osmo-bts-octphy/octphy_vty.c
index dbc903a..6e58ad4 100644
--- a/src/osmo-bts-octphy/octphy_vty.c
+++ b/src/osmo-bts-octphy/octphy_vty.c
@@ -38,6 +38,7 @@
#include <osmocom/vty/misc.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/vty.h>
@@ -51,149 +52,189 @@
SHOW_STR \
TRX_STR
+#define OCT_STR "OCTPHY Um interface\n"
+
static struct gsm_bts *vty_bts;
/* configuration */
-DEFUN(cfg_bts_phy_hwaddr, cfg_bts_phy_hwaddr_cmd,
- "phy-hw-addr HWADDR",
- "Configure the hardware addess of the OCTPHY\n"
+DEFUN(cfg_phy_hwaddr, cfg_phy_hwaddr_cmd,
+ "octphy hw-addr HWADDR",
+ OCT_STR "Configure the hardware addess of the OCTPHY\n"
"hardware address in aa:bb:cc:dd:ee:ff format\n")
{
- struct gsm_bts *bts = vty->index;
- struct gsm_bts_trx *trx = bts->c0;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_link *plink = vty->index;
int rc;
- rc = osmo_macaddr_parse(fl1h->phy_addr.sll_addr, argv[0]);
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Can only reconfigure a PHY link that is down%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ rc = osmo_macaddr_parse(plink->u.octphy.phy_addr.sll_addr, argv[0]);
if (rc < 0)
return CMD_WARNING;
return CMD_SUCCESS;
}
-DEFUN(cfg_bts_phy_netdev, cfg_bts_phy_netdev_cmd,
- "phy-netdev NAME",
- "Configure the hardware device towards the OCTPHY\n"
+DEFUN(cfg_phy_netdev, cfg_phy_netdev_cmd,
+ "octphy net-device NAME",
+ OCT_STR "Configure the hardware device towards the OCTPHY\n"
"Ethernet device name\n")
{
- struct gsm_bts *bts = vty->index;
- struct gsm_bts_trx *trx = bts->c0;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_link *plink = vty->index;
- if (fl1h->netdev_name)
- talloc_free(fl1h->netdev_name);
- fl1h->netdev_name = talloc_strdup(fl1h, argv[0]);
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Can only reconfigure a PHY link that is down%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (plink->u.octphy.netdev_name)
+ talloc_free(plink->u.octphy.netdev_name);
+ plink->u.octphy.netdev_name = talloc_strdup(plink, argv[0]);
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_rf_port_idx, cfg_trx_rf_port_idx_cmd,
- "rf-port-index <0-255>",
- "Configure the RF Port for this TRX\n"
+DEFUN(cfg_phy_rf_port_idx, cfg_phy_rf_port_idx_cmd,
+ "octphy rf-port-index <0-255>",
+ OCT_STR "Configure the RF Port for this TRX\n"
"RF Port Index\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_link *plink = vty->index;
- fl1h->config.rf_port_index = atoi(argv[0]);
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Can only reconfigure a PHY link that is down%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ plink->u.octphy.rf_port_index = atoi(argv[0]);
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_rx_gain_db, cfg_trx_rx_gain_db_cmd,
- "rx-gain <0-73>",
- "Configure the Rx Gain in dB\n"
+DEFUN(cfg_phy_rx_gain_db, cfg_phy_rx_gain_db_cmd,
+ "octphy rx-gain <0-73>",
+ OCT_STR "Configure the Rx Gain in dB\n"
"Rx gain in dB\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_link *plink = vty->index;
+
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Can only reconfigure a PHY link that is down%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
- fl1h->config.rx_gain_db = atoi(argv[0]);
+ plink->u.octphy.rx_gain_db = atoi(argv[0]);
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_tx_atten_db, cfg_trx_tx_atten_db_cmd,
- "tx-attenuation <0-359>",
- "Configure the Tx Attenuation in quarter-dB\n"
+DEFUN(cfg_phy_tx_atten_db, cfg_phy_tx_atten_db_cmd,
+ "octphy tx-attenuation <0-359>",
+ OCT_STR "Configure the Tx Attenuation in quarter-dB\n"
"Tx attenuation in quarter-dB\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
+ struct phy_link *plink = vty->index;
+
+ if (plink->state != PHY_LINK_SHUTDOWN) {
+ vty_out(vty, "Can only reconfigure a PHY link that is down%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
- fl1h->config.tx_atten_db = atoi(argv[0]);
+ plink->u.octphy.tx_atten_db = atoi(argv[0]);
return CMD_SUCCESS;
}
-DEFUN(get_rf_port_stats, get_rf_port_stats_cmd,
- "get-rf-port-stats <0-1>",
- "Obtain statistics for the RF Port\n"
+DEFUN(show_rf_port_stats, show_rf_port_stats_cmd,
+ "show phy <0-255> rf-port-stats <0-1>",
+ "Show statistics for the RF Port\n"
"RF Port Number\n")
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(vty_bts->c0);
+ int phy_nr = atoi(argv[0]);
+ struct phy_link *plink = phy_link_by_num(phy_nr);
- octphy_hw_get_rf_port_stats(fl1h, atoi(argv[0]));
+ octphy_hw_get_rf_port_stats(plink->u.octphy.hdl, atoi(argv[1]));
+
+ /* FIXME: Actually print to VTY, not just log */
+ vty_out(vty, "Please check the log file for the response%s",
+ VTY_NEWLINE);
return CMD_SUCCESS;
}
-DEFUN(get_clk_sync_stats, get_clk_sync_stats_cmd,
- "get-clk-sync-stats",
+DEFUN(show_clk_sync_stats, show_clk_sync_stats_cmd,
+ "show phy <0-255> clk-sync-stats",
"Obtain statistics for the Clock Sync Manager\n")
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(vty_bts->c0);
+ int phy_nr = atoi(argv[0]);
+ struct phy_link *plink = phy_link_by_num(phy_nr);
+
+ octphy_hw_get_clock_sync_stats(plink->u.octphy.hdl);
- octphy_hw_get_clock_sync_stats(fl1h);
+ /* FIXME: Actually print to VTY, not just log */
+ vty_out(vty, "Please check the log file for the response%s",
+ VTY_NEWLINE);
return CMD_SUCCESS;
}
+void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
+{
+ if (plink->u.octphy.netdev_name)
+ vty_out(vty, " netdev %s%s", plink->u.octphy.netdev_name,
+ VTY_NEWLINE);
+
+ vty_out(vty, " hw-addr %02x:%02x:%02x:%02x:%02x:%02x%s",
+ plink->u.octphy.phy_addr.sll_addr[0],
+ plink->u.octphy.phy_addr.sll_addr[1],
+ plink->u.octphy.phy_addr.sll_addr[2],
+ plink->u.octphy.phy_addr.sll_addr[3],
+ plink->u.octphy.phy_addr.sll_addr[4],
+ plink->u.octphy.phy_addr.sll_addr[5],
+ VTY_NEWLINE);
+ vty_out(vty, " rx-gain %u%s", plink->u.octphy.rx_gain_db,
+ VTY_NEWLINE);
+ vty_out(vty, " tx-attenuation %u%s", plink->u.octphy.tx_atten_db,
+ VTY_NEWLINE);
+ vty_out(vty, " rf-port-index %u%s", plink->u.octphy.rf_port_index,
+ VTY_NEWLINE);
+}
+
void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
- struct octphy_hdl *fl1h = trx_octphy_hdl(bts->c0);
-
- if (fl1h->netdev_name)
- vty_out(vty, " phy-netdev %s%s", fl1h->netdev_name,
- VTY_NEWLINE);
if (btsb->auto_band)
vty_out(vty, " auto-band%s", VTY_NEWLINE);
- vty_out(vty, " phy-hw-addr %02x:%02x:%02x:%02x:%02x:%02x%s",
- fl1h->phy_addr.sll_addr[0], fl1h->phy_addr.sll_addr[1],
- fl1h->phy_addr.sll_addr[2], fl1h->phy_addr.sll_addr[3],
- fl1h->phy_addr.sll_addr[4], fl1h->phy_addr.sll_addr[5],
- VTY_NEWLINE);
}
void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
{
- struct octphy_hdl *fl1h = trx_octphy_hdl(trx);
-
- vty_out(vty, " rx-gain %u%s", fl1h->config.rx_gain_db,
- VTY_NEWLINE);
- vty_out(vty, " tx-attenuation %u%s", fl1h->config.tx_atten_db,
- VTY_NEWLINE);
}
DEFUN(show_sys_info, show_sys_info_cmd,
- "show trx <0-255> system-information",
+ "show phy <0-255> system-information",
SHOW_TRX_STR "Display information about system\n")
{
- int trx_nr = atoi(argv[0]);
- struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
+ int phy_nr = atoi(argv[0]);
+ struct phy_link *plink = phy_link_by_num(phy_nr);
struct octphy_hdl *fl1h;
- int i;
- if (!trx) {
- vty_out(vty, "Cannot find TRX number %u%s",
- trx_nr, VTY_NEWLINE);
+ if (!plink) {
+ vty_out(vty, "Cannot find PHY number %u%s",
+ phy_nr, VTY_NEWLINE);
return CMD_WARNING;
}
- fl1h = trx_octphy_hdl(trx);
+ fl1h = plink->u.octphy.hdl;
vty_out(vty, "System Platform: '%s', Version: '%s'%s",
fl1h->info.system.platform, fl1h->info.system.version,
@@ -210,15 +251,14 @@ int bts_model_vty_init(struct gsm_bts *bts)
{
vty_bts = bts;
- install_element(BTS_NODE, &cfg_bts_phy_hwaddr_cmd);
- install_element(BTS_NODE, &cfg_bts_phy_netdev_cmd);
+ install_element(PHY_NODE, &cfg_phy_hwaddr_cmd);
+ install_element(PHY_NODE, &cfg_phy_netdev_cmd);
+ install_element(PHY_NODE, &cfg_phy_rf_port_idx_cmd);
+ install_element(PHY_NODE, &cfg_phy_rx_gain_db_cmd);
+ install_element(PHY_NODE, &cfg_phy_tx_atten_db_cmd);
- install_element(TRX_NODE, &cfg_trx_rf_port_idx_cmd);
- install_element(TRX_NODE, &cfg_trx_rx_gain_db_cmd);
- install_element(TRX_NODE, &cfg_trx_tx_atten_db_cmd);
-
- install_element_ve(&get_rf_port_stats_cmd);
- install_element_ve(&get_clk_sync_stats_cmd);
+ install_element_ve(&show_rf_port_stats_cmd);
+ install_element_ve(&show_clk_sync_stats_cmd);
install_element_ve(&show_sys_info_cmd);
return 0;
@@ -226,13 +266,5 @@ int bts_model_vty_init(struct gsm_bts *bts)
int bts_model_ctrl_cmds_install(struct gsm_bts *bts)
{
- /* FIXME: really ugly hack: We can only initialize the L1 intrface
- * after reading the config file, and this is the only call-back after
- * vty_read_config_fioe() at this point. Will be cleaned up with the
- * phy interface generalization patches coming up soon as part of the
- * multi-trx work */
- struct octphy_hdl *fl1h = bts->c0->role_bts.l1h;
- l1if_open(fl1h);
-
return 0;
}
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index edd4b7b..befaffd 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -59,7 +59,7 @@ static const uint8_t transceiver_chan_types[_GSM_PCHAN_MAX] = {
* create/destroy trx l1 instance
*/
-struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
+struct trx_l1h *l1if_open(struct phy_instance *pinst)
{
struct trx_l1h *l1h;
int rc;
@@ -67,11 +67,9 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
l1h = talloc_zero(tall_bts_ctx, struct trx_l1h);
if (!l1h)
return NULL;
- l1h->trx = trx;
- l1h->l1s.trx = trx;
- trx->role_bts.l1h = l1h;
+ l1h->phy_inst = pinst;
- trx_sched_init(&l1h->l1s);
+ trx_sched_init(&l1h->l1s, pinst->trx);
rc = trx_if_open(l1h);
if (rc < 0) {
@@ -83,7 +81,6 @@ struct trx_l1h *l1if_open(struct gsm_bts_trx *trx)
err:
l1if_close(l1h);
- trx->role_bts.l1h = NULL;
return NULL;
}
@@ -100,7 +97,8 @@ void l1if_reset(struct trx_l1h *l1h)
static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
{
- struct gsm_bts_trx *trx = l1h->trx;
+ struct phy_instance *pinst = l1h->phy_inst;
+ struct gsm_bts_trx *trx = pinst->trx;
uint8_t tn;
/* HACK, we should change state when we receive first clock from
@@ -132,10 +130,10 @@ static void check_transceiver_availability_trx(struct trx_l1h *l1h, int avail)
int check_transceiver_availability(struct gsm_bts *bts, int avail)
{
struct gsm_bts_trx *trx;
- struct trx_l1h *l1h;
llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
check_transceiver_availability_trx(l1h, avail);
}
return 0;
@@ -147,6 +145,7 @@ int check_transceiver_availability(struct gsm_bts *bts, int avail)
*/
int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
{
+ struct phy_link *plink = l1h->phy_inst->phy_link;
uint8_t tn;
if (!transceiver_available)
@@ -177,18 +176,23 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
}
/* after power on */
- if (l1h->config.rxgain_valid && !l1h->config.rxgain_sent) {
- trx_if_cmd_setrxgain(l1h, l1h->config.rxgain);
- l1h->config.rxgain_sent = 1;
- }
- if (l1h->config.power_valid && !l1h->config.power_sent) {
- trx_if_cmd_setpower(l1h, l1h->config.power);
- l1h->config.power_sent = 1;
+ if (l1h->phy_inst->num == 0) {
+ if (plink->u.osmotrx.rxgain_valid &&
+ !plink->u.osmotrx.rxgain_sent) {
+ trx_if_cmd_setrxgain(l1h, plink->u.osmotrx.rxgain);
+ plink->u.osmotrx.rxgain_sent = 1;
+ }
+ if (plink->u.osmotrx.power_valid &&
+ !plink->u.osmotrx.power_sent) {
+ trx_if_cmd_setpower(l1h, plink->u.osmotrx.power);
+ plink->u.osmotrx.power_sent = 1;
+ }
}
if (l1h->config.maxdly_valid && !l1h->config.maxdly_sent) {
trx_if_cmd_setmaxdly(l1h, l1h->config.maxdly);
l1h->config.maxdly_sent = 1;
}
+
for (tn = 0; tn < TRX_NR_TS; tn++) {
if (l1h->config.slottype_valid[tn]
&& !l1h->config.slottype_sent[tn]) {
@@ -203,8 +207,10 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
if (!l1h->config.poweron && !l1h->config.poweron_sent) {
trx_if_cmd_poweroff(l1h);
l1h->config.poweron_sent = 1;
- l1h->config.rxgain_sent = 0;
- l1h->config.power_sent = 0;
+ if (l1h->phy_inst->num == 0) {
+ plink->u.osmotrx.rxgain_sent = 0;
+ plink->u.osmotrx.power_sent = 0;
+ }
l1h->config.maxdly_sent = 0;
for (tn = 0; tn < TRX_NR_TS; tn++)
l1h->config.slottype_sent[tn] = 0;
@@ -216,17 +222,20 @@ int l1if_provision_transceiver_trx(struct trx_l1h *l1h)
int l1if_provision_transceiver(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
- struct trx_l1h *l1h;
uint8_t tn;
llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct phy_link *plink = pinst->phy_link;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
l1h->config.arfcn_sent = 0;
l1h->config.tsc_sent = 0;
l1h->config.bsic_sent = 0;
l1h->config.poweron_sent = 0;
- l1h->config.rxgain_sent = 0;
- l1h->config.power_sent = 0;
+ if (l1h->phy_inst->num == 0) {
+ plink->u.osmotrx.rxgain_sent = 0;
+ plink->u.osmotrx.power_sent = 0;
+ }
l1h->config.maxdly_sent = 0;
for (tn = 0; tn < TRX_NR_TS; tn++)
l1h->config.slottype_sent[tn] = 0;
@@ -242,7 +251,8 @@ int l1if_provision_transceiver(struct gsm_bts *bts)
/* initialize the layer1 */
static int trx_init(struct gsm_bts_trx *trx)
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
/* power on transceiver, if not already */
if (!l1h->config.poweron) {
@@ -264,7 +274,8 @@ static int trx_init(struct gsm_bts_trx *trx)
/* deactivate transceiver */
int bts_model_trx_close(struct gsm_bts_trx *trx)
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
enum gsm_phys_chan_config pchan = trx->ts[0].pchan;
/* close all logical channels and reset timeslots */
@@ -308,7 +319,6 @@ int bts_model_adjst_ms_pwr(struct gsm_lchan *lchan)
static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
{
struct gsm_bts_trx *trx;
- struct trx_l1h *l1h;
uint8_t bsic = bts->bsic;
struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
@@ -318,7 +328,8 @@ static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
}
llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
if (l1h->config.bsic != bsic || !l1h->config.bsic_valid) {
l1h->config.bsic = bsic;
l1h->config.bsic_valid = 1;
@@ -335,7 +346,9 @@ static uint8_t trx_set_bts(struct gsm_bts *bts, struct tlv_parsed *new_attr)
/* set trx attributes */
static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct phy_link *plink = pinst->phy_link;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
uint16_t arfcn = trx->arfcn;
if (l1h->config.arfcn != arfcn || !l1h->config.arfcn_valid) {
@@ -345,10 +358,10 @@ static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
l1if_provision_transceiver_trx(l1h);
}
- if (l1h->config.power_oml) {
- l1h->config.power = trx->max_power_red;
- l1h->config.power_valid = 1;
- l1h->config.power_sent = 0;
+ if (plink->u.osmotrx.power_oml && pinst->num == 0) {
+ plink->u.osmotrx.power = trx->max_power_red;
+ plink->u.osmotrx.power_valid = 1;
+ plink->u.osmotrx.power_sent = 0;
l1if_provision_transceiver_trx(l1h);
}
@@ -358,7 +371,8 @@ static uint8_t trx_set_trx(struct gsm_bts_trx *trx)
/* set ts attributes */
static uint8_t trx_set_ts(struct gsm_bts_trx_ts *ts)
{
- struct trx_l1h *l1h = trx_l1h_hdl(ts->trx);
+ struct phy_instance *pinst = trx_phy_instance(ts->trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
uint8_t tn = ts->nr;
uint16_t tsc = ts->tsc;
enum gsm_phys_chan_config pchan = ts->pchan;
@@ -439,6 +453,7 @@ static int l1if_set_ciphering(struct trx_l1h *l1h, struct gsm_lchan *lchan,
static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr,
enum osmo_mph_info_type type, uint8_t cause)
{
+ struct phy_instance *pinst = l1h->phy_inst;
struct osmo_phsap_prim l1sap;
memset(&l1sap, 0, sizeof(l1sap));
@@ -448,7 +463,7 @@ static int mph_info_chan_confirm(struct trx_l1h *l1h, uint8_t chan_nr,
l1sap.u.info.u.act_cnf.chan_nr = chan_nr;
l1sap.u.info.u.act_cnf.cause = cause;
- return l1sap_up(l1h->trx, &l1sap);
+ return l1sap_up(pinst->trx, &l1sap);
}
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn)
@@ -503,7 +518,8 @@ int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint
/* primitive from common part */
int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap)
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
struct msgb *msg = l1sap->oph.msg;
uint8_t chan_nr;
uint8_t tn, ss;
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h
index f492687..187303c 100644
--- a/src/osmo-bts-trx/l1_if.h
+++ b/src/osmo-bts-trx/l1_if.h
@@ -2,6 +2,7 @@
#define L1_IF_H_TRX
#include <osmo-bts/scheduler.h>
+#include <osmo-bts/phy_link.h>
struct trx_config {
uint8_t poweron; /* poweron(1) or poweroff(0) */
@@ -19,15 +20,6 @@ struct trx_config {
uint8_t bsic;
int bsic_sent;
- int rxgain_valid;
- int rxgain;
- int rxgain_sent;
-
- int power_valid;
- int power;
- int power_oml;
- int power_sent;
-
int maxdly_valid;
int maxdly;
int maxdly_sent;
@@ -42,7 +34,8 @@ struct trx_config {
struct trx_l1h {
struct llist_head trx_ctrl_list;
- struct gsm_bts_trx *trx;
+ //struct gsm_bts_trx *trx;
+ struct phy_instance *phy_inst;
struct osmo_fd trx_ofd_ctrl;
struct osmo_timer_list trx_ctrl_timer;
@@ -55,7 +48,7 @@ struct trx_l1h {
struct l1sched_trx l1s;
};
-struct trx_l1h *l1if_open(struct gsm_bts_trx *trx);
+struct trx_l1h *l1if_open(struct phy_instance *pinst);
void l1if_close(struct trx_l1h *l1h);
void l1if_reset(struct trx_l1h *l1h);
int check_transceiver_availability(struct gsm_bts *bts, int avail);
@@ -69,7 +62,8 @@ int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint
static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx->role_bts.l1h;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
return &l1h->l1s;
}
diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c
index aa6987c..62e8fe9 100644
--- a/src/osmo-bts-trx/main.c
+++ b/src/osmo-bts-trx/main.c
@@ -45,6 +45,7 @@
#include <osmocom/core/bits.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/phy_link.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/abis.h>
#include <osmo-bts/bts.h>
@@ -58,43 +59,6 @@
#include "l1_if.h"
#include "trx_if.h"
-int bts_model_init(struct gsm_bts *bts)
-{
- void *l1h;
- struct gsm_bts_trx *trx;
- struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
-
- btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
- if (!settsc_enabled && !setbsic_enabled)
- settsc_enabled = setbsic_enabled = 1;
-
- llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = l1if_open(trx);
- if (!l1h) {
- LOGP(DL1C, LOGL_FATAL, "Cannot open L1 Interface\n");
- goto error;
- }
-
- trx->role_bts.l1h = l1h;
- trx->nominal_power = 23;
-
- l1if_reset(l1h);
- }
-
- bts_model_vty_init(bts);
-
- return 0;
-
-error:
- llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx->role_bts.l1h;
- if (l1h)
- l1if_close(l1h);
- }
-
- return -EIO;
-}
-
/* dummy, since no direct dsp support */
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
{
@@ -103,10 +67,6 @@ uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
void bts_model_print_help()
{
- printf(
- " -I --local-trx-ip Local IP for transceiver to connect (default=%s)\n"
- , transceiver_ip
- );
}
int bts_model_handle_options(int argc, char **argv)
@@ -116,21 +76,16 @@ int bts_model_handle_options(int argc, char **argv)
while (1) {
int option_idx = 0, c;
static const struct option long_options[] = {
- /* specific to this hardware */
- { "local-trx-ip", 1, 0, 'I' },
{ 0, 0, 0, 0 }
};
- c = getopt_long(argc, argv, "I:",
+ c = getopt_long(argc, argv, "",
long_options, &option_idx);
if (c == -1)
break;
switch (c) {
- case 'I':
- transceiver_ip = strdup(optarg);
- break;
default:
num_errors++;
break;
@@ -140,6 +95,35 @@ int bts_model_handle_options(int argc, char **argv)
return num_errors;
}
+int bts_model_init(struct gsm_bts *bts)
+{
+ struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
+
+ btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
+
+ /* FIXME: this needs to be overridden with the real hardrware
+ * value */
+ bts->c0->nominal_power = 23;
+
+ bts_model_vty_init(bts);
+
+ return 0;
+}
+
+void bts_model_phy_link_set_defaults(struct phy_link *plink)
+{
+ plink->u.osmotrx.transceiver_ip = talloc_strdup(plink, "127.0.0.1");
+ plink->u.osmotrx.base_port_local = 5800;
+ plink->u.osmotrx.base_port_remote = 5700;
+ plink->u.osmotrx.clock_advance = 20;
+ plink->u.osmotrx.rts_advance = 5;
+ plink->u.osmotrx.power_oml = 1;
+}
+
+void bts_model_phy_instance_set_defaults(struct phy_instance *pinst)
+{
+}
+
int main(int argc, char **argv)
{
return bts_main(argc, argv);
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index ac9212b..15c05e8 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -55,12 +55,6 @@ uint32_t transceiver_last_fn;
static struct timeval transceiver_clock_tv;
static struct osmo_timer_list transceiver_clock_timer;
-/* clock advance for the transceiver */
-uint32_t trx_clock_advance = 20;
-
-/* advance RTS to give some time for data processing. (especially PCU) */
-uint32_t trx_rts_advance = 5; /* about 20ms */
-
/* Enable this to multiply TOA of RACH by 10.
* This is usefull to check tenth of timing advances with RSSI test tool.
* Note that regular phones will not work when using this test! */
@@ -1262,14 +1256,16 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
/* send time indication */
l1if_mph_time_ind(bts, fn);
- /* advance frame number, so the transceiver has more time until
- * it must be transmitted. */
- fn = (fn + trx_clock_advance) % GSM_HYPERFRAME;
-
/* process every TRX */
llist_for_each_entry(trx, &bts->trx_list, list) {
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
- struct l1sched_trx *l1t = trx_l1sched_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct phy_link *plink = pinst->phy_link;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
+ struct l1sched_trx *l1t = &l1h->l1s;
+
+ /* advance frame number, so the transceiver has more
+ * time until it must be transmitted. */
+ fn = (fn + plink->u.osmotrx.clock_advance) % GSM_HYPERFRAME;
/* we don't schedule, if power is off */
if (!trx_if_powered(l1h))
@@ -1279,7 +1275,7 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
for (tn = 0; tn < ARRAY_SIZE(l1t->ts); tn++) {
/* ready-to-send */
_sched_rts(l1t, tn,
- (fn + trx_rts_advance) % GSM_HYPERFRAME);
+ (fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME);
/* get burst for FN */
bits = _sched_dl_burst(l1t, tn, fn);
if (!bits) {
@@ -1323,10 +1319,12 @@ no_clock:
/* flush pending messages of transceiver */
/* close all logical channels and reset timeslots */
llist_for_each_entry(trx, &bts->trx_list, list) {
- trx_if_flush(trx_l1h_hdl(trx));
- trx_sched_reset(trx_l1sched_hdl(trx));
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
+ trx_if_flush(l1h);
+ trx_sched_reset(&l1h->l1s);
if (trx->nr == 0)
- trx_if_cmd_poweroff(trx_l1h_hdl(trx));
+ trx_if_cmd_poweroff(l1h);
}
/* tell BSC */
@@ -1461,7 +1459,8 @@ new_clock:
void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate)
{
- struct trx_l1h *l1h = trx_l1h_hdl(l1t->trx);
+ struct phy_instance *pinst = trx_phy_instance(l1t->trx);
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
if (activate)
trx_if_cmd_handover(l1h, tn, ss);
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index dbe6f68..a4c16dc 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -2,6 +2,7 @@
* OpenBTS TRX interface handling
*
* Copyright (C) 2013 Andreas Eversberg <jolly@eversberg.eu>
+ * Copyright (C) 2016 Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -34,6 +35,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/bits.h>
+#include <osmo-bts/phy_link.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/scheduler.h>
@@ -45,7 +47,6 @@
//#define TOA_RSSI_DEBUG
int transceiver_available = 0;
-const char *transceiver_ip = "127.0.0.1";
int settsc_enabled = 0;
int setbsic_enabled = 0;
@@ -53,11 +54,10 @@ int setbsic_enabled = 0;
* socket
*/
-static uint16_t base_port_local = 5800;
-
/* open socket */
-static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
- int (*cb)(struct osmo_fd *fd, unsigned int what))
+static int trx_udp_open(void *priv, struct osmo_fd *ofd, const char *host,
+ uint16_t port_local, uint16_t port_remote,
+ int (*cb)(struct osmo_fd *fd, unsigned int what))
{
struct sockaddr_storage sas;
struct sockaddr *sa = (struct sockaddr *)&sas;
@@ -71,8 +71,8 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
ofd->data = priv;
/* Listen / Binds */
- rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, 0, transceiver_ip,
- port, OSMO_SOCK_F_BIND);
+ rc = osmo_sock_init_ofd(ofd, AF_UNSPEC, SOCK_DGRAM, 0, host,
+ port_local, OSMO_SOCK_F_BIND);
if (rc < 0)
return rc;
@@ -84,10 +84,10 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
- sin->sin_port = htons(ntohs(sin->sin_port) - 100);
+ sin->sin_port = htons(port_remote);
} else if (sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
- sin6->sin6_port = htons(ntohs(sin6->sin6_port) - 100);
+ sin6->sin6_port = htons(port_remote);
} else {
return -EINVAL;
}
@@ -96,7 +96,6 @@ static int trx_udp_open(void *priv, struct osmo_fd *ofd, uint16_t port,
if (rc)
return rc;
-
return 0;
}
@@ -115,13 +114,11 @@ static void trx_udp_close(struct osmo_fd *ofd)
* clock
*/
-static struct osmo_fd trx_ofd_clk;
-
-
/* get clock from clock socket */
static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
{
- struct trx_l1h *l1h = ofd->data;
+ struct phy_link *plink = ofd->data;
+ struct phy_instance *pinst = phy_instance_by_num(plink, 0);
char buf[1500];
int len;
uint32_t fn;
@@ -146,7 +143,7 @@ static int trx_clk_read_cb(struct osmo_fd *ofd, unsigned int what)
"correctly, correcting to fn=%u\n", fn);
}
- trx_sched_clock(l1h->trx->bts, fn);
+ trx_sched_clock(pinst->trx->bts, fn);
return 0;
}
@@ -168,8 +165,8 @@ static void trx_ctrl_send(struct trx_l1h *l1h)
return;
tcm = llist_entry(l1h->trx_ctrl_list.next, struct trx_ctrl_msg, list);
- LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to trx=%u\n", tcm->cmd,
- l1h->trx->nr);
+ LOGP(DTRX, LOGL_DEBUG, "Sending control '%s' to %s\n", tcm->cmd,
+ phy_instance_name(l1h->phy_inst));
/* send command */
send(l1h->trx_ofd_ctrl.fd, tcm->cmd, strlen(tcm->cmd)+1, 0);
@@ -184,8 +181,8 @@ static void trx_ctrl_timer_cb(void *data)
{
struct trx_l1h *l1h = data;
- LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for trx=%d\n",
- l1h->trx->nr);
+ LOGP(DTRX, LOGL_NOTICE, "No response from transceiver for %s\n",
+ phy_instance_name(l1h->phy_inst));
trx_ctrl_send(l1h);
}
@@ -232,7 +229,8 @@ static int trx_ctrl_cmd(struct trx_l1h *l1h, int critical, const char *cmd,
int trx_if_cmd_poweroff(struct trx_l1h *l1h)
{
- if (l1h->trx->nr == 0)
+ struct phy_instance *pinst = l1h->phy_inst;
+ if (pinst->num == 0)
return trx_ctrl_cmd(l1h, 1, "POWEROFF", "");
else
return 0;
@@ -240,7 +238,8 @@ int trx_if_cmd_poweroff(struct trx_l1h *l1h)
int trx_if_cmd_poweron(struct trx_l1h *l1h)
{
- if (l1h->trx->nr == 0)
+ struct phy_instance *pinst = l1h->phy_inst;
+ if (pinst->num == 0)
return trx_ctrl_cmd(l1h, 1, "POWERON", "");
else
return 0;
@@ -324,6 +323,7 @@ int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss)
static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
{
struct trx_l1h *l1h = ofd->data;
+ struct phy_instance *pinst = l1h->phy_inst;
char buf[1500];
int len, resp;
@@ -374,11 +374,12 @@ static int trx_ctrl_read_cb(struct osmo_fd *ofd, unsigned int what)
sscanf(p + 1, "%d", &resp);
if (resp) {
LOGP(DTRX, (tcm->critical) ? LOGL_FATAL : LOGL_NOTICE,
- "transceiver (trx=%d) rejected TRX command "
- "with response: '%s'\n", l1h->trx->nr, buf);
+ "transceiver (%s) rejected TRX command "
+ "with response: '%s'\n",
+ phy_instance_name(pinst), buf);
rsp_error:
if (tcm->critical) {
- bts_shutdown(l1h->trx->bts, "SIGINT");
+ bts_shutdown(pinst->trx->bts, "SIGINT");
/* keep tcm list, so process is stopped */
return -EIO;
}
@@ -493,37 +494,91 @@ int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
* open/close
*/
+int bts_model_phy_link_open(struct phy_link *plink)
+{
+ struct phy_instance *pinst;
+ int rc;
+
+ phy_link_state_set(plink, PHY_LINK_CONNECTING);
+
+ /* open the shared/common clock socket */
+ rc = trx_udp_open(plink, &plink->u.osmotrx.trx_ofd_clk,
+ plink->u.osmotrx.transceiver_ip,
+ plink->u.osmotrx.base_port_local,
+ plink->u.osmotrx.base_port_remote,
+ trx_clk_read_cb);
+ if (rc < 0) {
+ phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
+ return -1;
+ }
+
+ /* open the individual instances with their ctrl+data sockets */
+ llist_for_each_entry(pinst, &plink->instances, list) {
+ pinst->u.osmotrx.hdl = l1if_open(pinst);
+ if (!pinst->u.osmotrx.hdl)
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ phy_link_state_set(plink, PHY_LINK_SHUTDOWN);
+ llist_for_each_entry(pinst, &plink->instances, list) {
+ if (pinst->u.osmotrx.hdl) {
+ trx_if_close(pinst->u.osmotrx.hdl);
+ pinst->u.osmotrx.hdl = NULL;
+ }
+ }
+ trx_udp_close(&plink->u.osmotrx.trx_ofd_clk);
+ return -1;
+}
+
+static uint16_t compute_port(struct phy_instance *pinst, int remote, int is_data)
+{
+ struct phy_link *plink = pinst->phy_link;
+ uint16_t inc = 1;
+
+ if (is_data)
+ inc = 2;
+
+ if (remote)
+ return plink->u.osmotrx.base_port_remote + (pinst->num << 1) + inc;
+ else
+ return plink->u.osmotrx.base_port_local + (pinst->num << 1) + inc;
+}
+
int trx_if_open(struct trx_l1h *l1h)
{
+ struct phy_instance *pinst = l1h->phy_inst;
+ struct phy_link *plink = pinst->phy_link;
int rc;
- LOGP(DTRX, LOGL_NOTICE, "Open transceiver for trx=%u\n", l1h->trx->nr);
+ LOGP(DTRX, LOGL_NOTICE, "Open transceiver for %s\n",
+ phy_instance_name(pinst));
/* initialize ctrl queue */
INIT_LLIST_HEAD(&l1h->trx_ctrl_list);
/* open sockets */
- if (l1h->trx->nr == 0) {
- rc = trx_udp_open(l1h, &trx_ofd_clk, base_port_local,
- trx_clk_read_cb);
- if (rc < 0)
- return rc;
- LOGP(DTRX, LOGL_NOTICE, "Waiting for transceiver send clock\n");
- }
rc = trx_udp_open(l1h, &l1h->trx_ofd_ctrl,
- base_port_local + (l1h->trx->nr << 1) + 1, trx_ctrl_read_cb);
+ plink->u.osmotrx.transceiver_ip,
+ compute_port(pinst, 0, 0),
+ compute_port(pinst, 1, 0), trx_ctrl_read_cb);
if (rc < 0)
goto err;
rc = trx_udp_open(l1h, &l1h->trx_ofd_data,
- base_port_local + (l1h->trx->nr << 1) + 2, trx_data_read_cb);
+ plink->u.osmotrx.transceiver_ip,
+ compute_port(pinst, 0, 1),
+ compute_port(pinst, 1, 1), trx_data_read_cb);
if (rc < 0)
goto err;
/* enable all slots */
l1h->config.slotmask = 0xff;
- if (l1h->trx->nr == 0)
- trx_if_cmd_poweroff(l1h);
+ /* FIXME: why was this only for TRX0 ? */
+ //if (l1h->trx->nr == 0)
+ trx_if_cmd_poweroff(l1h);
return 0;
@@ -548,13 +603,13 @@ void trx_if_flush(struct trx_l1h *l1h)
void trx_if_close(struct trx_l1h *l1h)
{
- LOGP(DTRX, LOGL_NOTICE, "Close transceiver for trx=%u\n", l1h->trx->nr);
+ struct phy_instance *pinst = l1h->phy_inst;
+ LOGP(DTRX, LOGL_NOTICE, "Close transceiver for %s\n",
+ phy_instance_name(pinst));
trx_if_flush(l1h);
/* close sockets */
- if (l1h->trx->nr == 0)
- trx_udp_close(&trx_ofd_clk);
trx_udp_close(&l1h->trx_ofd_ctrl);
trx_udp_close(&l1h->trx_ofd_data);
}
diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h
index 3862e2b..1ea0da9 100644
--- a/src/osmo-bts-trx/trx_if.h
+++ b/src/osmo-bts-trx/trx_if.h
@@ -6,6 +6,7 @@ extern const char *transceiver_ip;
extern int settsc_enabled;
extern int setbsic_enabled;
+struct trx_l1h;
struct trx_ctrl_msg {
struct llist_head list;
diff --git a/src/osmo-bts-trx/trx_vty.c b/src/osmo-bts-trx/trx_vty.c
index a4a7909..d2feea4 100644
--- a/src/osmo-bts-trx/trx_vty.c
+++ b/src/osmo-bts-trx/trx_vty.c
@@ -45,6 +45,8 @@
#include "trx_if.h"
#include "loops.h"
+#define OSMOTRX_STR "OsmoTRX Transceiver configuration\n"
+
static struct gsm_bts *vty_bts;
DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
@@ -53,7 +55,6 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
struct gsm_bts *bts = vty_bts;
struct gsm_bts_trx *trx;
struct trx_l1h *l1h;
- uint8_t tn;
if (!transceiver_available) {
vty_out(vty, "transceiver is not connected%s", VTY_NEWLINE);
@@ -63,7 +64,8 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
}
llist_for_each_entry(trx, &bts->trx_list, list) {
- l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = trx_phy_instance(trx);
+ l1h = pinst->u.osmotrx.hdl;
vty_out(vty, "TRX %d%s", trx->nr, VTY_NEWLINE);
vty_out(vty, " %s%s",
(l1h->config.poweron) ? "poweron":"poweroff",
@@ -85,56 +87,70 @@ DEFUN(show_transceiver, show_transceiver_cmd, "show transceiver",
VTY_NEWLINE);
else
vty_out(vty, " bisc : undefined%s", VTY_NEWLINE);
- if (l1h->config.rxgain_valid)
- vty_out(vty, " rxgain : %d%s", l1h->config.rxgain,
+ }
+
+ return CMD_SUCCESS;
+}
+
+
+static void show_phy_inst_single(struct vty *vty, struct phy_instance *pinst)
+{
+ uint8_t tn;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
+
+ vty_out(vty, "PHY Instance %s%s",
+ phy_instance_name(pinst), VTY_NEWLINE);
+ if (l1h->config.maxdly_valid)
+ vty_out(vty, " maxdly : %d%s", l1h->config.maxdly,
+ VTY_NEWLINE);
+ else
+ vty_out(vty, " maxdly : undefined%s", VTY_NEWLINE);
+ for (tn = 0; tn < TRX_NR_TS; tn++) {
+ if (!((1 << tn) & l1h->config.slotmask))
+ vty_out(vty, " slot #%d: unsupported%s", tn,
VTY_NEWLINE);
- else
- vty_out(vty, " rxgain : undefined%s", VTY_NEWLINE);
- if (l1h->config.power_valid)
- vty_out(vty, " power : %d%s", l1h->config.power,
+ else if (l1h->config.slottype_valid[tn])
+ vty_out(vty, " slot #%d: type %d%s", tn,
+ l1h->config.slottype[tn],
VTY_NEWLINE);
else
- vty_out(vty, " power : undefined%s", VTY_NEWLINE);
- if (l1h->config.maxdly_valid)
- vty_out(vty, " maxdly : %d%s", l1h->config.maxdly,
+ vty_out(vty, " slot #%d: undefined%s", tn,
VTY_NEWLINE);
- else
- vty_out(vty, " maxdly : undefined%s", VTY_NEWLINE);
- for (tn = 0; tn < TRX_NR_TS; tn++) {
- if (!((1 << tn) & l1h->config.slotmask))
- vty_out(vty, " slot #%d: unsupported%s", tn,
- VTY_NEWLINE);
- else if (l1h->config.slottype_valid[tn])
- vty_out(vty, " slot #%d: type %d%s", tn,
- l1h->config.slottype[tn],
- VTY_NEWLINE);
- else
- vty_out(vty, " slot #%d: undefined%s", tn,
- VTY_NEWLINE);
- }
}
-
- return CMD_SUCCESS;
}
-DEFUN(cfg_bts_fn_advance, cfg_bts_fn_advance_cmd,
- "fn-advance <0-30>",
- "Set the number of frames to be transmitted to transceiver in advance "
- "of current FN\n"
- "Advance in frames\n")
+static void show_phy_single(struct vty *vty, struct phy_link *plink)
{
- trx_clock_advance = atoi(argv[0]);
+ struct phy_instance *pinst;
- return CMD_SUCCESS;
+ vty_out(vty, "PHY %u%s", plink->num, VTY_NEWLINE);
+
+ if (plink->u.osmotrx.rxgain_valid)
+ vty_out(vty, " rx-gain : %d dB%s",
+ plink->u.osmotrx.rxgain, VTY_NEWLINE);
+ else
+ vty_out(vty, " rx-gain : undefined%s", VTY_NEWLINE);
+ if (plink->u.osmotrx.power_valid)
+ vty_out(vty, " tx-attenuation : %d dB%s",
+ plink->u.osmotrx.power, VTY_NEWLINE);
+ else
+ vty_out(vty, " tx-attenuation : undefined%s", VTY_NEWLINE);
+
+ llist_for_each_entry(pinst, &plink->instances, list)
+ show_phy_inst_single(vty, pinst);
}
-DEFUN(cfg_bts_rts_advance, cfg_bts_rts_advance_cmd,
- "rts-advance <0-30>",
- "Set the number of frames to be requested (PCU) in advance of current "
- "FN. Do not change this, unless you have a good reason!\n"
- "Advance in frames\n")
+DEFUN(show_phy, show_phy_cmd, "show phy",
+ SHOW_STR "Display information about the available PHYs")
{
- trx_rts_advance = atoi(argv[0]);
+ int i;
+
+ for (i = 0; i < 255; i++) {
+ struct phy_link *plink = phy_link_by_num(i);
+ if (!plink)
+ break;
+ show_phy_single(vty, plink);
+ }
return CMD_SUCCESS;
}
@@ -220,63 +236,14 @@ DEFUN(cfg_bts_no_setbsic, cfg_bts_no_setbsic_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_rxgain, cfg_trx_rxgain_cmd,
- "rxgain <0-50>",
- "Set the receiver gain in dB\n"
- "Gain in dB\n")
-{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
- l1h->config.rxgain = atoi(argv[0]);
- l1h->config.rxgain_valid = 1;
- l1h->config.rxgain_sent = 0;
- l1if_provision_transceiver_trx(l1h);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_power, cfg_trx_power_cmd,
- "power <0-50>",
- "Set the transmitter power dampening\n"
- "Power dampening in dB\n")
-{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
-
- l1h->config.power = atoi(argv[0]);
- l1h->config.power_oml = 0;
- l1h->config.power_valid = 1;
- l1h->config.power_sent = 0;
- l1if_provision_transceiver_trx(l1h);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_poweroml_, cfg_trx_power_oml_cmd,
- "power oml",
- "Set the transmitter power dampening\n"
- "Given by NM_ATT_RF_MAXPOWR_R (max power reduction) via OML\n")
-{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
-
- l1h->config.power = trx->max_power_red;
- l1h->config.power_oml = 1;
- l1h->config.power_valid = 1;
- l1h->config.power_sent = 0;
- l1if_provision_transceiver_trx(l1h);
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_trx_maxdly, cfg_trx_maxdly_cmd,
- "maxdly <0-31>",
+DEFUN(cfg_phyinst_maxdly, cfg_phyinst_maxdly_cmd,
+ "osmotrx maxdly <0-31>",
"Set the maximum delay of GSM symbols\n"
"GSM symbols (approx. 1.1km per symbol)\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = vty->index;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
l1h->config.maxdly = atoi(argv[0]);
l1h->config.maxdly_valid = 1;
@@ -286,7 +253,7 @@ DEFUN(cfg_trx_maxdly, cfg_trx_maxdly_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
+DEFUN(cfg_phyinst_slotmask, cfg_phyinst_slotmask_cmd,
"slotmask (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0) (1|0)",
"Set the supported slots\n"
"TS0 supported\nTS0 unsupported\nTS1 supported\nTS1 unsupported\n"
@@ -294,8 +261,8 @@ DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
"TS4 supported\nTS4 unsupported\nTS5 supported\nTS5 unsupported\n"
"TS6 supported\nTS6 unsupported\nTS7 supported\nTS7 unsupported\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_instance *pinst = vty->index;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
uint8_t tn;
l1h->config.slotmask = 0;
@@ -306,76 +273,171 @@ DEFUN(cfg_trx_slotmask, cfg_trx_slotmask_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_no_rxgain, cfg_trx_no_rxgain_cmd,
- "no rxgain <0-50>",
- NO_STR "Unset the receiver gain in dB\n"
+
+DEFUN(cfg_phy_fn_advance, cfg_phy_fn_advance_cmd,
+ "osmotrx fn-advance <0-30>",
+ OSMOTRX_STR
+ "Set the number of frames to be transmitted to transceiver in advance "
+ "of current FN\n"
+ "Advance in frames\n")
+{
+ struct phy_link *plink = vty->index;
+
+ plink->u.osmotrx.clock_advance = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_rts_advance, cfg_phy_rts_advance_cmd,
+ "osmotrx rts-advance <0-30>",
+ OSMOTRX_STR
+ "Set the number of frames to be requested (PCU) in advance of current "
+ "FN. Do not change this, unless you have a good reason!\n"
+ "Advance in frames\n")
+{
+ struct phy_link *plink = vty->index;
+
+ plink->u.osmotrx.rts_advance = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_rxgain, cfg_phy_rxgain_cmd,
+ "osmotrx rx-gain <0-50>",
+ OSMOTRX_STR
+ "Set the receiver gain in dB\n"
"Gain in dB\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_link *plink = vty->index;
- l1h->config.rxgain_valid = 0;
+ plink->u.osmotrx.rxgain = atoi(argv[0]);
+ plink->u.osmotrx.rxgain_valid = 1;
+ plink->u.osmotrx.rxgain_sent = 0;
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_no_power, cfg_trx_no_power_cmd,
- "no power <0-50>",
- NO_STR "Unset the transmitter power dampening\n"
- "Power dampening in dB\n")
+DEFUN(cfg_phy_tx_atten, cfg_phy_tx_atten_cmd,
+ "osmotrx tx-attenuation <0-50>",
+ OSMOTRX_STR
+ "Set the transmitter attenuation\n"
+ "Fixed attenuation in dB, overriding OML\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_link *plink = vty->index;
- l1h->config.power_valid = 0;
+ plink->u.osmotrx.power = atoi(argv[0]);
+ plink->u.osmotrx.power_oml = 0;
+ plink->u.osmotrx.power_valid = 1;
+ plink->u.osmotrx.power_sent = 0;
return CMD_SUCCESS;
}
-DEFUN(cfg_trx_no_maxdly, cfg_trx_no_maxdly_cmd,
- "no maxdly <0-31>",
- NO_STR "Unset the maximum delay of GSM symbols\n"
- "GSM symbols (approx. 1.1km per symbol)\n")
+DEFUN(cfg_phy_tx_atten_oml, cfg_phy_tx_atten_oml_cmd,
+ "osmotrx tx-attenuation oml",
+ OSMOTRX_STR
+ "Set the transmitter attenuation\n"
+ "Use NM_ATT_RF_MAXPOWR_R (max power reduction) from BSC via OML\n")
+{
+ struct phy_link *plink = vty->index;
+
+ plink->u.osmotrx.power_oml = 1;
+ plink->u.osmotrx.power_valid = 1;
+ plink->u.osmotrx.power_sent = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_no_rxgain, cfg_phy_no_rxgain_cmd,
+ "no osmotrx rx-gain",
+ NO_STR OSMOTRX_STR "Unset the receiver gain in dB\n")
+{
+ struct phy_link *plink = vty->index;
+
+ plink->u.osmotrx.rxgain_valid = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phy_no_tx_atten, cfg_phy_no_tx_atten_cmd,
+ "no osmotrx tx-attenuation",
+ NO_STR OSMOTRX_STR "Unset the transmitter attenuation\n")
{
- struct gsm_bts_trx *trx = vty->index;
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_link *plink = vty->index;
+
+ plink->u.osmotrx.power_valid = 0;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_phyinst_no_maxdly, cfg_phyinst_no_maxdly_cmd,
+ "no osmotrx maxdly",
+ NO_STR "Unset the maximum delay of GSM symbols\n")
+{
+ struct phy_instance *pinst = vty->index;
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
l1h->config.maxdly_valid = 0;
return CMD_SUCCESS;
}
-void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
+DEFUN(cfg_phy_transc_ip, cfg_phy_transc_ip_cmd,
+ "osmotrx ip HOST",
+ OSMOTRX_STR
+ "Set remote IP address\n"
+ "IP address of OsmoTRX\n")
{
- vty_out(vty, " fn-advance %d%s", trx_clock_advance, VTY_NEWLINE);
- vty_out(vty, " rts-advance %d%s", trx_rts_advance, VTY_NEWLINE);
+ struct phy_link *plink = vty->index;
- if (trx_ms_power_loop)
- vty_out(vty, " ms-power-loop %d%s", trx_target_rssi,
- VTY_NEWLINE);
- else
- vty_out(vty, " no ms-power-loop%s", VTY_NEWLINE);
- vty_out(vty, " %stiming-advance-loop%s", (trx_ta_loop) ? "":"no ",
- VTY_NEWLINE);
- if (settsc_enabled)
- vty_out(vty, " settsc%s", VTY_NEWLINE);
- if (setbsic_enabled)
- vty_out(vty, " setbsic%s", VTY_NEWLINE);
+ if (plink->u.osmotrx.transceiver_ip)
+ talloc_free(plink->u.osmotrx.transceiver_ip);
+ plink->u.osmotrx.transceiver_ip = talloc_strdup(plink, argv[0]);
+
+ return CMD_SUCCESS;
}
-void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
+DEFUN(cfg_phy_base_port, cfg_phy_base_port_cmd,
+ "osmotrx base-port (local|remote) <0-65535>",
+ OSMOTRX_STR "Set base UDP port number\n" "Local UDP port\n"
+ "Remote UDP port\n" "UDP base port number\n")
{
- struct trx_l1h *l1h = trx_l1h_hdl(trx);
+ struct phy_link *plink = vty->index;
+
+ if (!strcmp(argv[0], "local"))
+ plink->u.osmotrx.base_port_local = atoi(argv[1]);
+ else
+ plink->u.osmotrx.base_port_remote = atoi(argv[1]);
+
+ return CMD_SUCCESS;
+}
- if (l1h->config.rxgain_valid)
- vty_out(vty, " rxgain %d%s", l1h->config.rxgain, VTY_NEWLINE);
- if (l1h->config.power_valid) {
- if (l1h->config.power_oml)
- vty_out(vty, " power oml%s", VTY_NEWLINE);
+void bts_model_config_write_phy(struct vty *vty, struct phy_link *plink)
+{
+ if (plink->u.osmotrx.transceiver_ip)
+ vty_out(vty, " osmotrx ip %s%s",
+ plink->u.osmotrx.transceiver_ip, VTY_NEWLINE);
+
+ vty_out(vty, " osmotrx fn-advance %d%s",
+ plink->u.osmotrx.clock_advance, VTY_NEWLINE);
+ vty_out(vty, " osmotrx rts-advance %d%s",
+ plink->u.osmotrx.rts_advance, VTY_NEWLINE);
+ if (plink->u.osmotrx.rxgain_valid)
+ vty_out(vty, " osmotrx rx-gain %d%s",
+ plink->u.osmotrx.rxgain, VTY_NEWLINE);
+ if (plink->u.osmotrx.power_valid) {
+ if (plink->u.osmotrx.power_oml)
+ vty_out(vty, " osmotrx tx-attenuation oml%s", VTY_NEWLINE);
else
- vty_out(vty, " power %d%s", l1h->config.power,
- VTY_NEWLINE);
+ vty_out(vty, " osmotrx tx-attenuation %d%s",
+ plink->u.osmotrx.power, VTY_NEWLINE);
}
+}
+
+void bts_model_config_write_phy_inst(struct vty *vty, struct phy_instance *pinst)
+{
+ struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
+
if (l1h->config.maxdly_valid)
vty_out(vty, " maxdly %d%s", l1h->config.maxdly, VTY_NEWLINE);
if (l1h->config.slotmask != 0xff)
@@ -391,14 +453,32 @@ void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
VTY_NEWLINE);
}
+void bts_model_config_write_bts(struct vty *vty, struct gsm_bts *bts)
+{
+ if (trx_ms_power_loop)
+ vty_out(vty, " ms-power-loop %d%s", trx_target_rssi,
+ VTY_NEWLINE);
+ else
+ vty_out(vty, " no ms-power-loop%s", VTY_NEWLINE);
+ vty_out(vty, " %stiming-advance-loop%s", (trx_ta_loop) ? "":"no ",
+ VTY_NEWLINE);
+ if (settsc_enabled)
+ vty_out(vty, " settsc%s", VTY_NEWLINE);
+ if (setbsic_enabled)
+ vty_out(vty, " setbsic%s", VTY_NEWLINE);
+}
+
+void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx)
+{
+}
+
int bts_model_vty_init(struct gsm_bts *bts)
{
vty_bts = bts;
install_element_ve(&show_transceiver_cmd);
+ install_element_ve(&show_phy_cmd);
- install_element(BTS_NODE, &cfg_bts_fn_advance_cmd);
- install_element(BTS_NODE, &cfg_bts_rts_advance_cmd);
install_element(BTS_NODE, &cfg_bts_ms_power_loop_cmd);
install_element(BTS_NODE, &cfg_bts_no_ms_power_loop_cmd);
install_element(BTS_NODE, &cfg_bts_timing_advance_loop_cmd);
@@ -408,14 +488,19 @@ int bts_model_vty_init(struct gsm_bts *bts)
install_element(BTS_NODE, &cfg_bts_no_settsc_cmd);
install_element(BTS_NODE, &cfg_bts_no_setbsic_cmd);
- install_element(TRX_NODE, &cfg_trx_rxgain_cmd);
- install_element(TRX_NODE, &cfg_trx_power_cmd);
- install_element(TRX_NODE, &cfg_trx_power_oml_cmd);
- install_element(TRX_NODE, &cfg_trx_maxdly_cmd);
- install_element(TRX_NODE, &cfg_trx_slotmask_cmd);
- install_element(TRX_NODE, &cfg_trx_no_rxgain_cmd);
- install_element(TRX_NODE, &cfg_trx_no_power_cmd);
- install_element(TRX_NODE, &cfg_trx_no_maxdly_cmd);
+ install_element(PHY_NODE, &cfg_phy_base_port_cmd);
+ install_element(PHY_NODE, &cfg_phy_fn_advance_cmd);
+ install_element(PHY_NODE, &cfg_phy_rts_advance_cmd);
+ install_element(PHY_NODE, &cfg_phy_transc_ip_cmd);
+ install_element(PHY_NODE, &cfg_phy_rxgain_cmd);
+ install_element(PHY_NODE, &cfg_phy_tx_atten_cmd);
+ install_element(PHY_NODE, &cfg_phy_tx_atten_oml_cmd);
+ install_element(PHY_NODE, &cfg_phy_no_rxgain_cmd);
+ install_element(PHY_NODE, &cfg_phy_no_tx_atten_cmd);
+
+ install_element(PHY_INST_NODE, &cfg_phyinst_slotmask_cmd);
+ install_element(PHY_INST_NODE, &cfg_phyinst_maxdly_cmd);
+ install_element(PHY_INST_NODE, &cfg_phyinst_no_maxdly_cmd);
return 0;
}