General Instructions


System Requirements


  • A PC with a 64-bit processor or a virtual machine
  • The FreeBSD operating system, version 7.2 or 8.0
  • Internet access or a set of FreeBSD CDs (for installing packages)


  • A virtual machine image with FreeBSD and Blackhawk preinstalled
  • A computer with a virtual machine system that can run the image


If you have downloaded a virtual machine image with Blackhawk preinstalled, you can skip the rest of these installation steps.

Otherwise, follow these instructions:

  1. Acquire the source code package, e.g. from the web
  2. Install required packages by running the script
  3. Configure the build environment with the script
    • Note that you need to have the FreeBSD kernel sources installed. They can be acquired e.g. with sysinstall.
  4. Compile and install the prototype by running make all install.


# ./
# ./
# make all install

Root privileges are needed for installation.

Note: by default runs configure --prefix=/usr/local
This should be fine.

In order to avoid problems, disable multicore support by setting kern.smp.disabled=1 in FreeBSD’s /boot/loader.conf (and reboot):

# echo kern.smp.disabled=1 >> /boot/loader.conf
# shutdown -r now

Finally, the installation can be verified by running:

# make check

Running the checks can take several minutes.
Finally the output should say “All 7 tests passed” (Error: Test with EV_ADD|EV_ONESHOT FAILED printed in the middle of the check run is currently normal).

Uninstallation can be done with:

make uninstall

It’s adviceable to always uninstall a previous version of Blackhawk before upgrading to a new one.

If you want clean up the build system (i.e., automatically generated Makefiles etc.), run:

# make clean distclean
# ./

System Intialization

The local pub/sub system (kernel module, file system, and scope daemon) can be loaded by running loadps:

# loadps

If also the network daemons need to be started (More information about how to set up networking is provided below. The default settings will most probably not work in your environment.), the command is:

# loadps net

Unloading and reloading the system can be done with these commands respectively (append net if the network daemons have been loaded):

# unloadps
# reloadps

Alternatively, you can use the pubsub script installed in /usr/local/etc/rc.d/. It’s also possible to start the pub/sub system at boot time by adding pubsub_enable="YES" to the /etc/rc.conf file (but currently this is not recommended).


The source package contains these subdirectories:

  • examples – Programming and configuration examples
  • figures – Blackboard visualization tools
  • helpers – Helper applications
  • libpsirp – API
  • psfs – Kernel module and scope daemon
  • test – Test applications and scripts
  • utils – Utilities


Some simple applications come bundled with the pub/sub prototype. These test and helper apps are mainly useful for simple testing, and currently provide more value as examples than as pure functionality.

  • publish – publish a file or input from stdin
  • subscribe – subscribe to a publication
  • subevents – use kevents to get information about new publications and/or subscriptions
  • printscope – prints scope contents
  • psirptest – a tool that can do pretty much the same as the other apps above. Perhaps more of debugging value.


  • scopedScope Daemon: Updates scope publications when something is published
  • lairdPub/Sub Local Area Intradomain Rendezvous Daemon: Implements a simple link-local network rendezvous mechanism
  • netiodPub/Sub Network I/O Daemon: Implements packet sending, receiving, and forwarding

File System View

For debugging and backwards compatibility, the running pub/sub system can be viewed as a set of files and directories:

  • /pubsub/ – root directory for the file system view
  • /pubsub/sid/ – scopes are visible under the root
  • /pubsub/sid/rid/ – RIds (including SIds) are visible in scopes
  • /pubsub/sid/rid/meta – read-only view to the binary metadata
  • /pubsub/sid/rid/data – reading gives latest version; writing creates a publication version
  • /pubsub/sid/rid/vrid/ – view to a specific version; incl. data & meta
  • /pubsub/sid/rid/vrid/prid – read access to individual pages

Writing Applications

The libpsirp API with publish() and subscribe() functions can be used for application programming in C, Python, and Ruby. For more information, see Blackhawk – API Description, and also:

  • examples/c – C examples
  • examples/python – Python examples
  • examples/ruby – Ruby examples

In addition, the helpers and test apps can be used as examples.

Pub/Sub Networking


Note: Networking support in this release is still preliminary. For example, publication versioning, subscribe-before-publish, and demand paging are NOT supported. Moreover, only simple networks that resemble simple tree topologies should be set up. All links in the network should be point-to-point; connecting several nodes to the same broadcast link is not supported.

As mentioned above, the networking part can be initialized by adding net to the loading command. This starts the netiod and laird helpers.
By default, laird listens to events about new scopes appearing under Scope 0, and publishes metadata about new publications in these sub-scopes to the network via netiod.


Running make install creates a network configuration file template to /etc/netiod.conf. This file lists network interfaces (e.g., em0, em1, etc.) and their zFilters (for more information about the zFilter-based source routing mechanism, read e.g. Jokela et al.: LIPSIN: Line Speed Publish/Subscribe Inter-Networking). Configuration examples are also found under examples/zf.

The configuration file must be edited manually in order to set up a local network. Each outgoing link interface must have a link identifier (LId) and each node must have a virtual identifier pointing to itself. In addition, one node in the network is assumed to act as the local rendezvous node. Other nodes must have default routes pointing towards that node (i.e., zFilters with the link-Ids on the path ORed with the rendezvous node’s virtual Id).


We assume a network topology where nodes are connected to each other with separate links between their network interfaces. For example like this:


Firstly, edit /etc/netiod.conf in all nodes in your pub/sub network. See e.g. examples/zf/netiod.conf.node1/2/3 for examples.

  • Assing interfaces – both physical and virtual ones – static LIds (i.e., zFilters) that do not match each other.
    • You can use ifconfig to check what the interfaces your system has.
    • In this example, one node has an interface named em0 which is given ::11 as its LId. The LId of that node’s virtual interface is set to 00aa::.
  • Also configure default routes in each non-rendezvous node by ORing the LIds on the path to the selected rendezvous node.
    • Here, the LId of rendezvous node’s virtual interface is assumed to be 0000bb::.

Next, start the network daemons in all nodes:

reloadps net

Then, publish something in one of the nodes (for example with psirptest):

# psirptest -p -f inputfile -c sid -r rid        # sid != ::, sid != rid

Finally, subscribe synchronously to the given SId and RId in another node:

# psirptest -x -f outputfile -c sid -r rid

Known Limitations

Local pub/sub system:

  • Max. publication size is 512000 bytes
  • Max. number of publications in a scope is 125
  • Max. number of versions is also ~125

Networking part:

  • Reliable transport not implemented
  • Concurrent multi-publication reception not fully supported
  • Only whole publications can be subscribed to and received

No multi-core support.