Harald Welte has submitted this change and it was merged.

Change subject: vty: Implement VTY cfg parsing for current parameters
......................................................................


vty: Implement VTY cfg parsing for current parameters

At this stage, osmo-trx still uses the cmdline parameters top run the
device, but it is already able to parse all the same parameters from a
cfg file through the VTY and filling a trx_ctx structure which will be
later used to drive the device. Device config can be printed in the VTY
with "show trx".

Change-Id: Ie084c1b30b63f91c6e7640832ec1797d9e813832
---
M CommonLibs/trx_vty.c
M CommonLibs/trx_vty.h
M Transceiver52M/osmo-trx.cpp
3 files changed, 469 insertions(+), 2 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c
index b16cd24..843d19f 100644
--- a/CommonLibs/trx_vty.c
+++ b/CommonLibs/trx_vty.c
@@ -36,6 +36,22 @@
 
 static struct trx_ctx* g_trx_ctx;
 
+static const struct value_string clock_ref_names[] = {
+       { REF_INTERNAL, "internal" },
+       { REF_EXTERNAL, "external" },
+       { REF_GPS,      "gspdo" },
+       { 0,            NULL }
+};
+
+static const struct value_string filler_names[] = {
+       { FILLER_DUMMY,         "Dummy bursts" },
+       { FILLER_ZERO,          "Disabled" },
+       { FILLER_NORM_RAND,     "Normal bursts with random payload" },
+       { FILLER_EDGE_RAND,     "EDGE bursts with random payload" },
+       { FILLER_ACCESS_RAND,   "Access bursts with random payload" },
+       { 0,                    NULL }
+};
+
 struct trx_ctx *trx_from_vty(struct vty *v)
 {
         /* It can't hurt to force callers to continue to pass the vty instance
@@ -50,11 +66,18 @@
 
 enum trx_vty_node {
        TRX_NODE = _LAST_OSMOVTY_NODE + 1,
+       CHAN_NODE,
 };
 
 static struct cmd_node trx_node = {
        TRX_NODE,
        "%s(config-trx)# ",
+       1,
+};
+
+static struct cmd_node chan_node = {
+       CHAN_NODE,
+       "%s(config-trx-chan)# ",
        1,
 };
 
@@ -84,15 +107,364 @@
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_remote_ip, cfg_remote_ip_cmd,
+       "remote-ip A.B.C.D",
+       "Set the IP address for the remote BTS\n"
+       "IPv4 Address\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       osmo_talloc_replace_string(trx, &trx->cfg.remote_addr, argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_base_port, cfg_base_port_cmd,
+       "base-port <1-65535>",
+       "Set the TRX Base Port\n"
+       "TRX Base Port\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.base_port = atoi(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_dev_args, cfg_dev_args_cmd,
+       "dev-args DESC",
+       "Set the device-specific arguments to pass to the device\n"
+       "Device-specific arguments\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       osmo_talloc_replace_string(trx, &trx->cfg.dev_args, argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_tx_sps, cfg_tx_sps_cmd,
+       "tx-sps (1|4)",
+       "Set the Tx Samples-per-Symbol\n"
+       "Tx Samples-per-Symbol\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.tx_sps = atoi(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_rx_sps, cfg_rx_sps_cmd,
+       "rx-sps (1|4)",
+       "Set the Rx Samples-per-Symbol\n"
+       "Rx Samples-per-Symbol\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.rx_sps = atoi(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_test_rtsc, cfg_test_rtsc_cmd,
+       "test rtsc <0-7>",
+       "Set the Random Normal Burst test mode with TSC\n"
+       "TSC\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       if (trx->cfg.rach_delay_set) {
+               vty_out(vty, "rach-delay and rtsc options are 
mutual-exclusive%s",
+                       VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       trx->cfg.rtsc_set = true;
+       trx->cfg.rtsc = atoi(argv[0]);
+       if (!trx->cfg.egprs) /* Don't override egprs which sets different 
filler */
+               trx->cfg.filler = FILLER_NORM_RAND;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_test_rach_delay, cfg_test_rach_delay_cmd,
+       "test rach-delay <0-68>",
+       "Set the Random Access Burst test mode with delay\n"
+       "RACH delay\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       if (trx->cfg.rtsc_set) {
+               vty_out(vty, "rach-delay and rtsc options are 
mutual-exclusive%s",
+                       VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       if (trx->cfg.egprs) {
+               vty_out(vty, "rach-delay and egprs options are 
mutual-exclusive%s",
+                       VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+
+       trx->cfg.rach_delay_set = true;
+       trx->cfg.rach_delay = atoi(argv[0]);
+       trx->cfg.filler = FILLER_ACCESS_RAND;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_clock_ref, cfg_clock_ref_cmd,
+       "clock-ref (internal|external|gpsdo)",
+       "Set the Reference Clock\n"
+       "Enable internal referece (default)\n"
+       "Enable external 10 MHz reference\n"
+       "Enable GPSDO reference\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.clock_ref = get_string_value(clock_ref_names, argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_multi_arfcn, cfg_multi_arfcn_cmd,
+       "multi-arfcn (disable|enable)",
+       "Enable multi-ARFCN transceiver (default=disable)\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       if (strcmp("disable", argv[0]) == 0) {
+               trx->cfg.multi_arfcn = false;
+       } else if (strcmp("enable", argv[0]) == 0) {
+               trx->cfg.multi_arfcn = true;
+       } else {
+               return CMD_WARNING;
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_offset, cfg_offset_cmd,
+       "offset FLOAT",
+       "Set the baseband frequency offset (default=0, auto)\n"
+       "Baseband Frequency Offset\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.offset = atof(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_rssi_offset, cfg_rssi_offset_cmd,
+       "rssi-offset FLOAT",
+       "Set the RSSI to dBm offset in dB (default=0)\n"
+       "RSSI to dBm offset in dB\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.rssi_offset = atof(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_swap_channels, cfg_swap_channels_cmd,
+       "swap-channels (disable|enable)",
+       "Swap channels (default=disable)\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       if (strcmp("disable", argv[0]) == 0) {
+               trx->cfg.swap_channels = false;
+       } else if (strcmp("enable", argv[0]) == 0) {
+               trx->cfg.swap_channels = true;
+       } else {
+               return CMD_WARNING;
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_egprs, cfg_egprs_cmd,
+       "egprs (disable|enable)",
+       "Enable EDGE receiver (default=disable)\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       if (strcmp("disable", argv[0]) == 0) {
+               trx->cfg.egprs = false;
+       } else if (strcmp("enable", argv[0]) == 0) {
+               trx->cfg.egprs = true;
+               trx->cfg.filler = FILLER_EDGE_RAND;
+       } else {
+               return CMD_WARNING;
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_rt_prio, cfg_rt_prio_cmd,
+       "rt-prio <1-32>",
+       "Set the SCHED_RR real-time priority\n"
+       "Real time priority\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.sched_rr = atoi(argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_filler, cfg_filler_cmd,
+       "filler dummy",
+       "Enable C0 filler table\n"
+       "Dummy method\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+
+       trx->cfg.filler = FILLER_DUMMY;
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_chan, cfg_chan_cmd,
+       "chan <0-100>",
+       "Select a channel to configure\n"
+       "Channel index\n")
+{
+       struct trx_ctx *trx = trx_from_vty(vty);
+       int idx = atoi(argv[0]);
+
+       if (idx >= TRX_CHAN_MAX) {
+               vty_out(vty, "Chan list full.%s", VTY_NEWLINE);
+               return CMD_WARNING;
+       }
+       if (trx->cfg.num_chans < idx) { /* Unexisting or creating 
non-consecutive */
+               vty_out(vty, "Non-existent or non-consecutive chan %d.%s",
+                               idx, VTY_NEWLINE);
+               return CMD_WARNING;
+       } else if (trx->cfg.num_chans == idx)  { /* creating it */
+               trx->cfg.num_chans++;
+               trx->cfg.chans[idx].trx = trx;
+               trx->cfg.chans[idx].idx = idx;
+       }
+
+       vty->node = CHAN_NODE;
+       vty->index = &trx->cfg.chans[idx];
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_chan_rx_path, cfg_chan_rx_path_cmd,
+       "rx-path NAME",
+       "Set the Rx Path\n"
+       "Rx Path name\n")
+{
+       struct trx_chan *chan = vty->index;
+
+       osmo_talloc_replace_string(chan->trx, &chan->rx_path, argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_chan_tx_path, cfg_chan_tx_path_cmd,
+       "tx-path NAME",
+       "Set the Tx Path\n"
+       "Tx Path name\n")
+{
+       struct trx_chan *chan = vty->index;
+
+       osmo_talloc_replace_string(chan->trx, &chan->tx_path, argv[0]);
+
+       return CMD_SUCCESS;
+}
+
+static int dummy_config_write(struct vty *v)
+{
+       return CMD_SUCCESS;
+}
+
 static int config_write_trx(struct vty *vty)
 {
+       struct trx_chan *chan;
+       int i;
        struct trx_ctx *trx = trx_from_vty(vty);
 
        vty_out(vty, "trx%s", VTY_NEWLINE);
        if (trx->cfg.bind_addr)
                vty_out(vty, " bind-ip %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
+       if (trx->cfg.remote_addr)
+               vty_out(vty, " remote-ip %s%s", trx->cfg.remote_addr, 
VTY_NEWLINE);
+       if (trx->cfg.base_port != DEFAULT_TRX_PORT)
+               vty_out(vty, " base-port %u%s", trx->cfg.base_port, 
VTY_NEWLINE);
+       if (trx->cfg.dev_args)
+               vty_out(vty, " dev-args %s%s", trx->cfg.dev_args, VTY_NEWLINE);
+       if (trx->cfg.tx_sps != DEFAULT_TX_SPS)
+               vty_out(vty, " tx-sps %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
+       if (trx->cfg.rx_sps != DEFAULT_RX_SPS)
+               vty_out(vty, " rx-sps %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
+       if (trx->cfg.rtsc_set)
+               vty_out(vty, " test rtsc %u%s", trx->cfg.rtsc, VTY_NEWLINE);
+       if (trx->cfg.rach_delay_set)
+               vty_out(vty, " test rach-delay %u%s", trx->cfg.rach_delay, 
VTY_NEWLINE);
+       if (trx->cfg.clock_ref != REF_INTERNAL)
+               vty_out(vty, " clock-ref %s%s", 
get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
+       vty_out(vty, " multi-arfcn %s%s", trx->cfg.multi_arfcn ? "enable" : 
"disable", VTY_NEWLINE);
+       if (trx->cfg.offset != 0)
+               vty_out(vty, " offset %f%s", trx->cfg.offset, VTY_NEWLINE);
+       if (trx->cfg.rssi_offset != 0)
+               vty_out(vty, " rssi-offset %f%s", trx->cfg.rssi_offset, 
VTY_NEWLINE);
+       vty_out(vty, " swap-channels %s%s", trx->cfg.swap_channels ? "enable" : 
"disable", VTY_NEWLINE);
+       vty_out(vty, " egprs %s%s", trx->cfg.egprs ? "enable" : "disable", 
VTY_NEWLINE);
+       if (trx->cfg.sched_rr != 0)
+               vty_out(vty, " rt-prio %u%s", trx->cfg.sched_rr, VTY_NEWLINE);
+
+       for (i = 0; i < trx->cfg.num_chans; i++) {
+               chan = &trx->cfg.chans[i];
+               vty_out(vty, " chan %u%s", chan->idx, VTY_NEWLINE);
+               if (chan->rx_path)
+                       vty_out(vty, " rx-path %s%s", chan->rx_path, 
VTY_NEWLINE);
+               if (chan->tx_path)
+                       vty_out(vty, " tx-path %s%s", chan->tx_path, 
VTY_NEWLINE);
+       }
 
        return CMD_SUCCESS;
+}
+
+static void trx_dump_vty(struct vty *vty, struct trx_ctx *trx)
+{
+       struct trx_chan *chan;
+       int i;
+       vty_out(vty, "TRX Config:%s", VTY_NEWLINE);
+       vty_out(vty, " Local IP: %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
+       vty_out(vty, " Remote IP: %s%s", trx->cfg.remote_addr, VTY_NEWLINE);
+       vty_out(vty, " TRX Base Port: %u%s", trx->cfg.base_port, VTY_NEWLINE);
+       vty_out(vty, " Device args: %s%s", trx->cfg.dev_args, VTY_NEWLINE);
+       vty_out(vty, " Tx Samples-per-Symbol: %u%s", trx->cfg.tx_sps, 
VTY_NEWLINE);
+       vty_out(vty, " Rx Samples-per-Symbol: %u%s", trx->cfg.rx_sps, 
VTY_NEWLINE);
+       vty_out(vty, " Test Mode: TSC: %u (%s)%s", trx->cfg.rtsc,
+               trx->cfg.rtsc_set ? "Enabled" : "Disabled", VTY_NEWLINE);
+       vty_out(vty, " Test Mode: RACH Delay: %u (%s)%s", trx->cfg.rach_delay,
+               trx->cfg.rach_delay_set ? "Enabled" : "Disabled", VTY_NEWLINE);
+       vty_out(vty, " C0 Filler Table: %s%s", get_value_string(filler_names, 
trx->cfg.filler), VTY_NEWLINE);
+       vty_out(vty, " Clock Reference: %s%s", 
get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
+       vty_out(vty, " Multi-Carrier: %s%s", trx->cfg.multi_arfcn ? "Enabled" : 
"Disabled", VTY_NEWLINE);
+       vty_out(vty, " Tuning offset: %f%s", trx->cfg.offset, VTY_NEWLINE);
+       vty_out(vty, " RSSI to dBm offset: %f%s", trx->cfg.rssi_offset, 
VTY_NEWLINE);
+       vty_out(vty, " Swap channels: %s%s", trx->cfg.swap_channels ? "Enabled" 
: "Disabled", VTY_NEWLINE);
+       vty_out(vty, " EDGE support: %s%s", trx->cfg.egprs ? "Enabled" : 
"Disabled", VTY_NEWLINE);
+       vty_out(vty, " Real Time Priority: %u (%s)%s", trx->cfg.sched_rr,
+               trx->cfg.sched_rr ? "Enabled" : "Disabled", VTY_NEWLINE);
+       vty_out(vty, " Channels: %u%s", trx->cfg.num_chans, VTY_NEWLINE);
+       for (i = 0; i < trx->cfg.num_chans; i++) {
+               chan = &trx->cfg.chans[i];
+               vty_out(vty, "  Channel %u:%s", chan->idx, VTY_NEWLINE);
+               if (chan->rx_path)
+                       vty_out(vty, "   Rx Path: %s%s", chan->rx_path, 
VTY_NEWLINE);
+               if (chan->tx_path)
+                       vty_out(vty, "   Tx Path: %s%s", chan->tx_path, 
VTY_NEWLINE);
+       }
 }
 
 DEFUN(show_trx, show_trx_cmd,
@@ -101,7 +473,7 @@
 {
        struct trx_ctx *trx = trx_from_vty(vty);
 
-       vty_out(vty, "TRX: Bound to %s%s", trx->cfg.bind_addr, VTY_NEWLINE);
+       trx_dump_vty(vty, trx);
 
        return CMD_SUCCESS;
 }
@@ -110,6 +482,7 @@
 {
        switch (node) {
        case TRX_NODE:
+       case CHAN_NODE:
                return 1;
        default:
                return 0;
@@ -121,6 +494,11 @@
        switch (vty->node) {
        case TRX_NODE:
                vty->node = CONFIG_NODE;
+               vty->index = NULL;
+               vty->index_sub = NULL;
+               break;
+       case CHAN_NODE:
+               vty->node = TRX_NODE;
                vty->index = NULL;
                vty->index_sub = NULL;
                break;
@@ -148,6 +526,20 @@
        .is_config_node = trx_vty_is_config_node,
 };
 
+struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx)
+{
+       struct trx_ctx * trx = talloc_zero(talloc_ctx, struct trx_ctx);
+
+       trx->cfg.bind_addr =  talloc_strdup(trx, DEFAULT_TRX_IP);
+       trx->cfg.remote_addr = talloc_strdup(trx, DEFAULT_TRX_IP);
+       trx->cfg.base_port = DEFAULT_TRX_PORT;
+       trx->cfg.tx_sps = DEFAULT_TX_SPS;
+       trx->cfg.rx_sps = DEFAULT_RX_SPS;
+       trx->cfg.filler = FILLER_ZERO;
+
+       return trx;
+}
+
 int trx_vty_init(struct trx_ctx* trx)
 {
        g_trx_ctx = trx;
@@ -157,6 +549,26 @@
 
        install_node(&trx_node, config_write_trx);
        install_element(TRX_NODE, &cfg_bind_ip_cmd);
+       install_element(TRX_NODE, &cfg_remote_ip_cmd);
+       install_element(TRX_NODE, &cfg_base_port_cmd);
+       install_element(TRX_NODE, &cfg_dev_args_cmd);
+       install_element(TRX_NODE, &cfg_tx_sps_cmd);
+       install_element(TRX_NODE, &cfg_rx_sps_cmd);
+       install_element(TRX_NODE, &cfg_test_rtsc_cmd);
+       install_element(TRX_NODE, &cfg_test_rach_delay_cmd);
+       install_element(TRX_NODE, &cfg_clock_ref_cmd);
+       install_element(TRX_NODE, &cfg_multi_arfcn_cmd);
+       install_element(TRX_NODE, &cfg_offset_cmd);
+       install_element(TRX_NODE, &cfg_rssi_offset_cmd);
+       install_element(TRX_NODE, &cfg_swap_channels_cmd);
+       install_element(TRX_NODE, &cfg_egprs_cmd);
+       install_element(TRX_NODE, &cfg_rt_prio_cmd);
+       install_element(TRX_NODE, &cfg_filler_cmd);
+
+       install_element(TRX_NODE, &cfg_chan_cmd);
+       install_node(&chan_node, dummy_config_write);
+       install_element(CHAN_NODE, &cfg_chan_rx_path_cmd);
+       install_element(CHAN_NODE, &cfg_chan_tx_path_cmd);
 
        return 0;
 }
diff --git a/CommonLibs/trx_vty.h b/CommonLibs/trx_vty.h
index 74af31b..c921722 100644
--- a/CommonLibs/trx_vty.h
+++ b/CommonLibs/trx_vty.h
@@ -2,12 +2,67 @@
 
 #include <osmocom/vty/command.h>
 
+#include "config_defs.h"
+
 extern struct vty_app_info g_vty_info;
+
+#define TRX_CHAN_MAX 8
+
+/* Samples-per-symbol for downlink path
+ *     4 - Uses precision modulator (more computation, less distortion)
+ *     1 - Uses minimized modulator (less computation, more distortion)
+ *
+ *     Other values are invalid. Receive path (uplink) is always
+ *     downsampled to 1 sps. Default to 4 sps for all cases.
+ */
+#define DEFAULT_TX_SPS         4
+
+/*
+ * Samples-per-symbol for uplink (receiver) path
+ *     Do not modify this value. EDGE configures 4 sps automatically on
+ *     B200/B210 devices only. Use of 4 sps on the receive path for other
+ *     configurations is not supported.
+ */
+#define DEFAULT_RX_SPS         1
+
+/* Default configuration parameters */
+#define DEFAULT_TRX_PORT       5700
+#define DEFAULT_TRX_IP         "127.0.0.1"
+#define DEFAULT_CHANS          1
+
+struct trx_ctx;
+
+struct trx_chan {
+       struct trx_ctx *trx; /* backpointer */
+       unsigned int idx; /* channel index */
+       char *rx_path;
+       char *tx_path;
+};
 
 struct trx_ctx {
        struct {
                char *bind_addr;
+               char *remote_addr;
+               char *dev_args;
+               unsigned int base_port;
+               unsigned int tx_sps;
+               unsigned int rx_sps;
+               unsigned int rtsc;
+               bool rtsc_set;
+               unsigned int rach_delay;
+               bool rach_delay_set;
+               enum ReferenceType clock_ref;
+               enum FillerType filler;
+               bool multi_arfcn;
+               double offset;
+               double rssi_offset;
+               bool swap_channels;
+               bool egprs;
+               unsigned int sched_rr;
+               unsigned int num_chans;
+               struct trx_chan chans[TRX_CHAN_MAX];
        } cfg;
 };
 
 int trx_vty_init(struct trx_ctx* trx);
+struct trx_ctx *vty_trx_ctx_alloc(void *talloc_ctx);
diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp
index dc4e1c8..7bc025f 100644
--- a/Transceiver52M/osmo-trx.cpp
+++ b/Transceiver52M/osmo-trx.cpp
@@ -566,7 +566,7 @@
 
        setup_signal_handlers();
 
-       g_trx_ctx = talloc_zero(tall_trx_ctx, struct trx_ctx);
+       g_trx_ctx = vty_trx_ctx_alloc(tall_trx_ctx);
 
 #ifdef HAVE_SSE3
        printf("Info: SSE3 support compiled in");

-- 
To view, visit https://gerrit.osmocom.org/6650
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie084c1b30b63f91c6e7640832ec1797d9e813832
Gerrit-PatchSet: 6
Gerrit-Project: osmo-trx
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: Vadim Yanitskiy <axilira...@gmail.com>

Reply via email to