ControlPort: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
(Fix formatting - html entities)
mNo edit summary
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= ControlPort =
= ControlPort =


ControlPort is a new interface for standardizing remote procedure calls in GNU Radio:
ControlPort is an interface for standardizing remote procedure calls in GNU Radio:


* Remote control and visualization.
* Remote control and visualization.
Line 45: Line 45:
** Reset button resets the performance counter stats.
** Reset button resets the performance counter stats.
** Pause button stops the remote flowgraph; click again to restart.
** Pause button stops the remote flowgraph; click again to restart.
** 'Tile' button or Ctrl-t will tile all open windows.
** 'Tile' button or Ctrl-t will tile all open windows.  
== Apache Thrift ==
 
ControlPort requires a [https://thrift.apache.org/ Thrift]. On some systems, the default version shipped with the OS is too old, so you will need to install it.
 
=== Notes for Ubuntu 20.04 ===
I have not managed to compile Thrift from source, but instead used a recent version from apt:
 
* Install Apache Thrift 0.13 from the repository:
** apt install libthrift-dev
 
* Build and install:
** <code>cmake</code>
** Check that in the Gnuradio enabled components <code>* * thrift</code> appears.
** <code>make</code>
** <code>sudo make install</code>
 
* From pip i needed to pick some specific Versions to start gr-perf-monitorx:
** <code>pip install "pygccxml>=2.0.0"</code>
** <code>pip install "networkx==2.4"</code>
** <code>pip install pygraphviz</code>


== Apache Thrift ==


ControlPort requires a [https://thrift.apache.org/ Thrift] version of 0.9.2 or greater. On many systems, this is not the default version shipped with the OS, so we will need to install it. The [https://github.com/gnuradio/recipes/blob/master/apache-thrift.lwr PyBOMBS recipe] builds an acceptable version.


=== Very outdated information for Ubuntu 14.04 ===
To manually install the required version of Thrift on Ubuntu 14.04:
To manually install the required version of Thrift on Ubuntu 14.04:


Line 57: Line 76:
** Install "python-twisted" package (it provide the "trial" package that thrift requires and it fails silently if it does not find it...)
** Install "python-twisted" package (it provide the "trial" package that thrift requires and it fails silently if it does not find it...)
** I also had to install "openssl-devel" (it contains the "libcrypto" library that thrift requires) on Fedora
** I also had to install "openssl-devel" (it contains the "libcrypto" library that thrift requires) on Fedora
** Install libtool (if not already present on your system)
* Clone the repo and check out version 0.9.2:
* Clone the repo and check out version 0.9.2:
** <code>git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift</code>
** <code>git clone https://github.com/apache/thrift.git thrift</code>
** <code>cd thrift</code>
** <code>cd thrift</code>
** <code>git checkout 0.9.2</code>
** <code>git checkout 0.9.2</code>
Line 82: Line 102:


* source $prefix/setup_env.sh
* source $prefix/setup_env.sh
=== Thrift 0.9.2 Shutdown Patch ===
Iff you run into problems with segfaults during shutdown, we might have a patch that fixes that in Thrift itself. You can find it in the source code:
source:gnuradio-runtime/lib/controlport/thrift/thrift-codebase-shutdown-patch.diff
And there is a README in that directory as well to explain a bit about the situation. I suspect this will not affect most people, and for anyone who comes across it, you'll only see it when shutting down your application.


=== Building GNU Radio ===
=== Building GNU Radio ===
Line 124: Line 136:
<pre>gnuradio-config-info --enabled-components
<pre>gnuradio-config-info --enabled-components
python-support;testing-support;volk;gnuradio-runtime;gr-ctrlport;* thrift;... (more components)</pre>
python-support;testing-support;volk;gnuradio-runtime;gr-ctrlport;* thrift;... (more components)</pre>
== Historical Background ==
I'm slapping this here so that a bit of historical background is preserved – it's absolutely not critical to understanding or working with Control Port, at all. Alas, it would be sad if all this historical knowledge was lost, especially if someone ends up designing RPC backends and would like to reconstruct ''why'' GNU Radio took the a given path of implementation. [[User:MarcusMueller|Marcus Müller, the]] ([[User talk:MarcusMueller|talk]]) 17:47, 25 January 2023 (UTC)
Matrix chat excerpt:<div class="mw-collapsible mw-collapsed">
control port (or controlport, or ctrlport, all the same) is in the end a set of hooks in the GNU Radio runtime (and very very few blocks – you can register your own probes in your block if you want to) that you can enable (or not) at compile time which can do things like "record how long it takes between this start and this end point" (most typically used probe for that is a timer around the general_work), but also things like buffer fill level.
Now, you've got probes, nice, but you need to be able to query them somehow. That's why there's historically (and I mean that – long before I heard of GNU Radio the first time) been an RPC backend, based on ICE, which you could query. Never used that, actually!
So, there used to be things that compiled ICE interface definitions into code and the whole shabang. Then, something happened on the legal side (I honestly don't know), and ICE basically became infeasible over night (I wasn't really involved with GNU Radio at that point yet, so specifics are completely outside my knowledge).
So, someone sat down (got paid to sit down, even, maybe? Don't know!) and wrote a thrift backend. You'll find it in gnuradio-runtime as rpcserver[-_az]* stuff. Including the rather cool performance monitor etc.
Fast forward another couple of years: Thrift is a dependency nightmare. Not only different versions on different distros, but also versions with very different capabilities (it's very rare that you find a build of thrift libraries that enables all language bindings and all features. They have, or at least used to have, a bit of a code rot issue, where nobody could tell you whether binding for language XYZ is currently in a great shape. And if debian and fedora and suse all exclude half of the bindings from their builds, you can guess how long it'll take people to fix things). That basically led to a world where very few GNU Radio users actually could build a GNU Radio with controlport probes enabled, and with the thrift RPC backend enabled.
Then, compilers got better: because the backend was rarely used, me and prior maintainers rarely looked at the backend code; in fact, it was disabled for a lot of our CI, as due to missing a working version of thrift, it would have required building GNU Radio with a randomly picked different  self-built thrift, which in the end "nobody" else would have used, and since a significant (basically, all) the time fixing bugs with the rpcserver backend back then was spent on hunting down thrift version incompatibilities, building a rpcserver backend against some non-standard thrift simply got low priority.
But as compilers got better, they started to slap us for the code in rpcserver_thrift: There was a longstanding bug where the author of that code decided it was fine to store a reference passed as constructor argument in the class; small issue with that: this reference was to a locally created object, whose life time ended afterwards. So, that was a load of UB.
Lately, people have stepped up to tackle that, but I'd be lying if I said that it's a top priority – basically, when we made 3.8 to 3.10, we were focussing on making the commonly used tools (shutdown, PMTs, message passing, being able to "wake up" a block if it's not blocking in work) less broken, and GR4.0 is definitely more RPC friendly, from the grounds up, so we kind of shifted our "how can we improve RPC-ability?" energy on "future" GNU Radio, instead of trying to fix that in currently deployed versions (simply because we knew there was so much better we could have done with respect to RPC that RPC-heavy use cases wouldn't be really happy with the limited amount of things ctrlport does, and would have been well-advised to contribute to a redesign of GR in order to make RPC, distributed processing, structured run-time reconfiguration, inspectability, remote logging, … better. You get the idea.)
Btw, the control port probes can have significant performance impact if enabled at compile time, depending on your platform. Basically, if your "get the time now at high resolution" call is done by a vdso purely within user space, it's kind of OK, but if your machine has to fall back, because your operating system, or the underlying virtualized hardware, don't support that, you get two context switches per thing you want to time, which is hella expensive
</div>

Latest revision as of 13:12, 18 March 2024

ControlPort

ControlPort is an interface for standardizing remote procedure calls in GNU Radio:

  • Remote control and visualization.
  • Use of ControlPort to enable debugging without requiring extra debug streams.
  • Abstracted interface for different back-end solutions.
  • No additional CPU usage while no monitoring is occurring.
  • Can connect multiple remotes to same GNU Radio application.
  • Can also have single ControlPort app control multiple GR apps.

Each block defines interfaces to control data members.

Defines ‘get’ and ‘set’ interface to query and update values of blocks.

Currently, we are using the Apache Thrift project for the ControlPort backend. See below for details.

Use preference files to control the state of ControlPort:

  • Edit section [ControlPort] in gnuradio-runtime.conf.
    • on: Set to True/On/1 or False/Off/0. Default=False.
    • edges_list: toggle exporting list of flowgraph edges (used by gr-perf-monitorx).

Comes with a generic utility to allow you to see all interfaces of a flowgraph (make sure firewalls are set up to allow the connection):

  • gr-ctrlport-monitor <ip address or host name> <port>
    • Tables lists all interfaces.
    • Update time defaults to 1 second and can be changed through the top menu.
    • Double clicking will open up an interfaces default GUI style handler (if it doesn't, no default exists).
    • Right click on an item will pop up a menu to select which type of plot to use.
    • Drag-and-drop any item on an existing graph to plot multiple items.
    • 'Tile' button or Ctrl-t will tile all open windows.
  • gr-perf-monitorx <ip address or host name> <port>
    • Shows graph of the remote flowgraph.
      • Blue nodes are blocks, and the size is proportional to the 'work time' performance counter.
      • Red edges are buffers, and the size and darkness are proportional to the '% output buffer full" performance counter.
    • Updates every 1 second.
    • Change type of performance counter statistic: instantaneous, average, or variance.
    • Change the clock used in the performance counters.
      • Thread is how much compute time is spent in a block's work function.
      • Monotonic is how much wall clock time has passed between entering and exiting work.
    • Can open Runtime and Buffer Tables to see table or bar graphs of percent of each perf counter.
    • Can drag-and-drop blocks around the canvas to reorganize the display.
    • Reset button resets the performance counter stats.
    • Pause button stops the remote flowgraph; click again to restart.
    • 'Tile' button or Ctrl-t will tile all open windows.

Apache Thrift

ControlPort requires a Thrift. On some systems, the default version shipped with the OS is too old, so you will need to install it.

Notes for Ubuntu 20.04

I have not managed to compile Thrift from source, but instead used a recent version from apt:

  • Install Apache Thrift 0.13 from the repository:
    • apt install libthrift-dev
  • Build and install:
    • cmake
    • Check that in the Gnuradio enabled components * * thrift appears.
    • make
    • sudo make install
  • From pip i needed to pick some specific Versions to start gr-perf-monitorx:
    • pip install "pygccxml>=2.0.0"
    • pip install "networkx==2.4"
    • pip install pygraphviz


Very outdated information for Ubuntu 14.04

To manually install the required version of Thrift on Ubuntu 14.04:

  • Install some additional dependencies:
    • apt-get install bison flex libevent-dev
    • Install "python-twisted" package (it provide the "trial" package that thrift requires and it fails silently if it does not find it...)
    • I also had to install "openssl-devel" (it contains the "libcrypto" library that thrift requires) on Fedora
    • Install libtool (if not already present on your system)
  • Clone the repo and check out version 0.9.2:
  • Configure:
    • ./bootstrap
    • ./configure --prefix=$prefix PY_PREFIX=$prefix --with-cpp --with-python CXXFLAGS="-DNDEBUG"
  • Make sure C++ and Python Libraries are supported.
  • Build and install:
    • make
    • sudo make install

Normally, you can install using $prefix=/usr. If using anything other than that, you also need the PY_PREFIX set because Thrift ignores the normal --prefix for Python installations and this forces the issue.

Depending on your linux distribution, thrift's configure system fails to set the suffixes for Boost's unittest library correctly. You can fix that by hand, or work around it by disabling tests. Similar issues arise from the tutorials being built, lua and perl bindings; PyBOMBS disables those. To make thrift build without modification, I had to disable all this on a fedora 21:

/configure --prefix=/home/marcus/.usrlocal --disable-tests --with-lua=no --disable-tutorial --with-perl=no

This installs the Python files into $prefix/lib/python2.7/site-packages, which may not be in PYTHONPATH, so add it:

  • export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/site-packages

Or, to make it sticky between reboots, add the same line to your .bashrc file. If using pybombs, consider "source-ing" a generated environment file (pybombs env) ala

  • source $prefix/setup_env.sh

Building GNU Radio

When building GNU Radio, make sure that the build script is picking up Thrift and running everything properly. When cmake finishes, it prints out a list of enabled components, and you should see this:

-- ######################################################
-- # Gnuradio enabled components                         
-- ######################################################
--   * python-support
--   * testing-support
--   * gnuradio-runtime
--   * gr-ctrlport
--   * * thrift
.... (more components)

If you don't see the "* * thrift" at this stage, cmake did not find the necessary C++ and Python support. Look back at the full cmake output to find the section on ControlPort. A successful configuration looks like:

-- Configuring gr-ctrlport support...
--   Dependency Boost_FOUND = 1
--   Dependency SWIG_FOUND = TRUE
--   Dependency SWIG_VERSION_CHECK = TRUE
--   Dependency ENABLE_GNURADIO_RUNTIME = ON
--   Enabling gr-ctrlport support.
--   Override with -DENABLE_GR_CTRLPORT=ON/OFF
-- Loading build date Thu, 06 Aug 2015 16:47:33 into constants...
-- Loading version 3.7.8 into constants...
-- 
-- Python checking for Thrift
-- Python checking for Thrift - found
-- Found and enabling Thrift backend to ControlPort
-- Running thrift to build C++ bindings

If you have installed GNU Radio already, you can check to see what components are available and look for "* thrift" in this list:

gnuradio-config-info --enabled-components
python-support;testing-support;volk;gnuradio-runtime;gr-ctrlport;* thrift;... (more components)

Historical Background

I'm slapping this here so that a bit of historical background is preserved – it's absolutely not critical to understanding or working with Control Port, at all. Alas, it would be sad if all this historical knowledge was lost, especially if someone ends up designing RPC backends and would like to reconstruct why GNU Radio took the a given path of implementation. Marcus Müller, the (talk) 17:47, 25 January 2023 (UTC)

Matrix chat excerpt:

control port (or controlport, or ctrlport, all the same) is in the end a set of hooks in the GNU Radio runtime (and very very few blocks – you can register your own probes in your block if you want to) that you can enable (or not) at compile time which can do things like "record how long it takes between this start and this end point" (most typically used probe for that is a timer around the general_work), but also things like buffer fill level.

Now, you've got probes, nice, but you need to be able to query them somehow. That's why there's historically (and I mean that – long before I heard of GNU Radio the first time) been an RPC backend, based on ICE, which you could query. Never used that, actually! So, there used to be things that compiled ICE interface definitions into code and the whole shabang. Then, something happened on the legal side (I honestly don't know), and ICE basically became infeasible over night (I wasn't really involved with GNU Radio at that point yet, so specifics are completely outside my knowledge).

So, someone sat down (got paid to sit down, even, maybe? Don't know!) and wrote a thrift backend. You'll find it in gnuradio-runtime as rpcserver[-_az]* stuff. Including the rather cool performance monitor etc.

Fast forward another couple of years: Thrift is a dependency nightmare. Not only different versions on different distros, but also versions with very different capabilities (it's very rare that you find a build of thrift libraries that enables all language bindings and all features. They have, or at least used to have, a bit of a code rot issue, where nobody could tell you whether binding for language XYZ is currently in a great shape. And if debian and fedora and suse all exclude half of the bindings from their builds, you can guess how long it'll take people to fix things). That basically led to a world where very few GNU Radio users actually could build a GNU Radio with controlport probes enabled, and with the thrift RPC backend enabled. Then, compilers got better: because the backend was rarely used, me and prior maintainers rarely looked at the backend code; in fact, it was disabled for a lot of our CI, as due to missing a working version of thrift, it would have required building GNU Radio with a randomly picked different self-built thrift, which in the end "nobody" else would have used, and since a significant (basically, all) the time fixing bugs with the rpcserver backend back then was spent on hunting down thrift version incompatibilities, building a rpcserver backend against some non-standard thrift simply got low priority.

But as compilers got better, they started to slap us for the code in rpcserver_thrift: There was a longstanding bug where the author of that code decided it was fine to store a reference passed as constructor argument in the class; small issue with that: this reference was to a locally created object, whose life time ended afterwards. So, that was a load of UB. Lately, people have stepped up to tackle that, but I'd be lying if I said that it's a top priority – basically, when we made 3.8 to 3.10, we were focussing on making the commonly used tools (shutdown, PMTs, message passing, being able to "wake up" a block if it's not blocking in work) less broken, and GR4.0 is definitely more RPC friendly, from the grounds up, so we kind of shifted our "how can we improve RPC-ability?" energy on "future" GNU Radio, instead of trying to fix that in currently deployed versions (simply because we knew there was so much better we could have done with respect to RPC that RPC-heavy use cases wouldn't be really happy with the limited amount of things ctrlport does, and would have been well-advised to contribute to a redesign of GR in order to make RPC, distributed processing, structured run-time reconfiguration, inspectability, remote logging, … better. You get the idea.)

Btw, the control port probes can have significant performance impact if enabled at compile time, depending on your platform. Basically, if your "get the time now at high resolution" call is done by a vdso purely within user space, it's kind of OK, but if your machine has to fall back, because your operating system, or the underlying virtualized hardware, don't support that, you get two context switches per thing you want to time, which is hella expensive