vty: Introduce command 'gsmtap-remote-host' and 'gsmtap-category enable-all'

Related: OS#5306
Change-Id: Ibc6f78c46831b3c90ee3e97300fc13dc441df4c8
Pau Espin 1 year ago
parent afd9393a2d
commit 13866f02a2

@ -422,3 +422,71 @@ encoded in CS1, so in case any control block is sent from time to time it's
accomplished and there's no penalty. However, if only EGPRS downlink data is sent
over that time frame, then the scheduler will force sending a RLCMAC Dummy
=== Configuring GSMTAP tracing
In addition to being able to obtain pcap protocol traces of the NS/BSSGP
communication and the text-based logging from the OsmoPCU software, there is
also the capability of tracing all communication on the radio interface related
to PS. To do so, OsmoPCU can encapsulate MAC blocks (23-155 byte messages at the
L2-L1 interface depending on coding scheme) into _GSMTAP_ and send them via
UDP/IP. At that point, they can be captured with utilities like *tcpdump* or
*tshark* for further analysis by the *wireshark* protocol analyzer.
In order to activate this feature, you first need to make sure to specify
the remote address of _GSMTAP_ host in the configuration file. In most
cases, using for passing the messages over the loopback (`lo`)
device will be sufficient:
.Example: Enabling GSMTAP Um-frame logging to localhost
gsmtap-remote-host <1>
<1> Destination address for _GSMTAP_ Um-frames
NOTE: Changing this parameter at run-time will not affect the existing
_GSMTAP_ connection, full program restart is required.
NOTE: Command line parameters `-i` and `--gsmtap-ip` have been deprecated.
OsmoPCU can selectively trace such messages based on different categories, for
both Ul and Dl. For a complete list of cateogry values, please refer to the
_OsmoPCU VTY reference manual_ <<vty-ref-osmopcu>>.
For example, to enable GSMTAP tracing for all DL EGPRS rlcmac data blocks, you
can use the `gsmtap-category dl-data-egprs` command at the `pcu` node of the
.Example: Enabling GSMTAP for for all DL EGPRS rlcmac data blocks
OsmoPCU> enable
OsmoPCU# configure terminal
OsmoPCU(config)# pcu
OsmoPCU(pcu)# gsmtap-category dl-data-egprs
OsmoPCU(trx)# write <1>
<1> the `write` command will make the configuration persistent in the
configuration file. This is not required if you wish to enable GSMTAP
only in the current session of OsmoPCU.
De-activation can be performed similarly by using the `no gsmtap-category
dl-data-egprs` command at the `pcu` node of the OsmoPCU VTY.
It may be useful to enable all categories with a few exceptions, or vice versa
disable everything using one command. For this purpose, the VTY provides
`gsmtap-category enable-all` and `gsmtap-category disable-all` commands.
.Example: Enabling all categoriess except _dl-dummy_
gsmtap-category enable-all <1>
no gsmtap-category dl-dummy <2>
<1> Enable all available SAPIs
<2> Exclude DL RLCMAC blocks
From the moment they are enabled via VTY, GSMTAP messages will be
generated and sent in UDP encapsulation to the IANA-registered UDP port
for GSMTAP (4729) of the specified remote address.

@ -25,5 +25,3 @@ options:
Use the given MCC instead of that provided by BTS via PCU socket
*-n, --mnc 'MNC'*::
Use the given MNC instead of that provided by BTS via PCU socket
*-i, --gsmtap-ip 'A.B.C.D'*::
Send Um interface trace via GSMTAP to specified IP address

@ -117,6 +117,7 @@ struct gprs_pcu {
struct gsmtap_inst *gsmtap;
uint32_t gsmtap_categ_mask;
char *gsmtap_remote_host;
struct llist_head bts_list; /* list of gprs_rlcmac_bts */

@ -64,7 +64,7 @@ extern void *bv_tall_ctx;
static int quit = 0;
static int rt_prio = -1;
static bool daemonize = false;
static const char *gsmtap_addr = "localhost"; // FIXME: use gengetopt's default value instead
static const char *gsmtap_addr;
static void print_help()
@ -75,7 +75,6 @@ static void print_help()
" -n --mnc MNC Use given MNC instead of value provided by BTS\n"
" -V --version Print version\n"
" -D --daemonize Fork the process into a background daemon\n"
" -i --gsmtap-ip The destination IP used for GSMTAP\n"
"\nVTY reference generation:\n"
" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n"
" --vty-ref-xml Generate the VTY reference XML output and exit.\n"
@ -161,6 +160,8 @@ static void handle_options(int argc, char **argv)
case 'i':
gsmtap_addr = optarg;
fprintf(stderr, "Command line argument '-i' is deprecated, use VTY "
"parameter 'gsmtap-remote-host %s' instead.\n", gsmtap_addr);
case 'r':
rt_prio = atoi(optarg);
@ -258,13 +259,6 @@ int main(int argc, char *argv[])
pcu->gsmtap = gsmtap_source_init(gsmtap_addr, GSMTAP_UDP_PORT, 1);
if (pcu->gsmtap)
fprintf(stderr, "Failed to initialize GSMTAP for %s\n", gsmtap_addr);
pcu->nsi = gprs_ns2_instantiate(tall_pcu_ctx, gprs_ns_prim_cb, NULL);
if (!pcu->nsi) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
@ -283,6 +277,31 @@ int main(int argc, char *argv[])
fprintf(stderr, "No config file: '%s' Using default config.\n",
/* Accept a GSMTAP host from VTY config, but a commandline option overrides that. */
if (gsmtap_addr) {
if (pcu->gsmtap_remote_host != NULL) {
"Command line argument '-i %s' overrides "
"'gsmtap-remote-host %s' from the config file\n",
gsmtap_addr, pcu->gsmtap_remote_host);
pcu->gsmtap_remote_host = talloc_strdup(pcu, gsmtap_addr);
if (pcu->gsmtap_remote_host) {
"Setting up GSMTAP Um forwarding to '%s:%u'\n",
pcu->gsmtap_remote_host, GSMTAP_UDP_PORT);
pcu->gsmtap = gsmtap_source_init(pcu->gsmtap_remote_host,
if (pcu->gsmtap == NULL) {
fprintf(stderr, "Failed during gsmtap_source_init()\n");
rc = telnet_init_dynif(tall_pcu_ctx, NULL, vty_get_bind_addr(),
if (rc < 0) {

@ -70,6 +70,49 @@ static const struct value_string pcu_gsmtap_categ_help[] = {
{ 0, NULL }
"gsmtap-remote-host [HOSTNAME]",
"Enable GSMTAP Um logging (see also 'gsmtap-category')\n"
"Remote IP address or hostname ('localhost' if omitted)\n")
osmo_talloc_replace_string(the_pcu, &the_pcu->gsmtap_remote_host,
argc > 0 ? argv[0] : "localhost");
if (vty->type != VTY_FILE)
vty_out(vty, "%% This command requires restart%s", VTY_NEWLINE);
"no gsmtap-remote-host",
NO_STR "Disable GSMTAP Um logging\n")
if (the_pcu->gsmtap_remote_host)
if (vty->type != VTY_FILE)
vty_out(vty, "%% This command requires restart%s", VTY_NEWLINE);
DEFUN(cfg_pcu_gsmtap_sapi_all, pcucfg_pcu_gsmtap_categ_all_cmd,
"gsmtap-category (enable-all|disable-all)",
"Enable/disable sending of UL/DL messages over GSMTAP\n"
"Enable all kinds of messages (all categories)\n"
"Disable all kinds of messages (all categories)\n")
if (strcmp(argv[0], "enable-all") == 0)
the_pcu->gsmtap_categ_mask = UINT32_MAX;
the_pcu->gsmtap_categ_mask = 0x00;
DEFUN(cfg_pcu_gsmtap_categ, cfg_pcu_gsmtap_categ_cmd, "HIDDEN", "HIDDEN")
@ -238,11 +281,14 @@ static int config_write_pcu(struct vty *vty)
if (strcmp(the_pcu->pcu_sock_path, PCU_SOCK_DEFAULT))
vty_out(vty, " pcu-socket %s%s", the_pcu->pcu_sock_path, VTY_NEWLINE);
if (the_pcu->gsmtap_remote_host)
vty_out(vty, " gsmtap-remote-host %s%s", the_pcu->gsmtap_remote_host, VTY_NEWLINE);
for (i = 0; i < 32; i++) {
uint32_t cs = ((uint32_t)1 << i);
if (the_pcu->gsmtap_categ_mask & cs) {
vty_out(vty, " gsmtap-category %s%s",
get_value_string(pcu_gsmtap_categ_names, i), VTY_NEWLINE);
if (the_pcu->gsmtap_categ_mask & ((uint32_t)1 << i)) {
const char *category_buf;
if (!(category_buf = get_value_string_or_null(pcu_gsmtap_categ_names, i)))
vty_out(vty, " gsmtap-category %s%s", category_buf, VTY_NEWLINE);
@ -1294,6 +1340,9 @@ int pcu_vty_init(void)
install_element(PCU_NODE, &cfg_pcu_no_dl_tbf_preemptive_retransmission_cmd);
install_element(PCU_NODE, &cfg_pcu_ms_idle_time_cmd);
install_element(PCU_NODE, &cfg_pcu_no_ms_idle_time_cmd);
install_element(PCU_NODE, &cfg_pcu_gsmtap_remote_host_cmd);
install_element(PCU_NODE, &cfg_pcu_no_gsmtap_remote_host_cmd);
install_element(PCU_NODE, &pcucfg_pcu_gsmtap_categ_all_cmd);
install_element(PCU_NODE, &cfg_pcu_gsmtap_categ_cmd);
install_element(PCU_NODE, &cfg_pcu_no_gsmtap_categ_cmd);
install_element(PCU_NODE, &cfg_pcu_sock_cmd);