io-pkt-v4-hc, io-pkt-v6-hc

Updated: April 19, 2023

Networking manager


io-pkt-variant [-DIS] [-d driver [driver_options]] [-i instance] [-P priority]
               [-p protocol [protocol_options]] [-q interval] [-r priority]
               [-t threads] [-U string] [-u string] [-w interval]

where variant is v4-hc or v6-hc.

Runs on:

QNX Neutrino


Run the resource manager/protocol layer stack context in a dedicated POSIX thread. By default this is off. This option can offer a performance improvement if you're sending and receiving TCP/IP traffic from applications on a multicore system.
-d driver [driver_options]
Start the specified devnp-* driver:
  • You can specify driver without the devnp- prefix or the .so extension. For example, to start the driver, specify -d e1000.
  • If you want to load a specific version of a driver, specify the full path of the module (e.g., /lib/dll/

The driver_options argument is a list of driver-specific options that the stack passes to the driver.


Use commas, not spaces, to separate the options.

The stack processes various driver options; for more information, see Generic driver options,” below.

Don't acquire _NTO_TCTL_IO_PRIV in this instance of io-pkt (see ThreadCtl() in the C Library Reference). With this option enabled, drivers loaded into io-pkt can't perform any operation that requires _NTO_TCTL_IO_PRIV, and they can't queue interrupts in an ISR.
-i instance
The stack instance number, which is useful if you're running multiple instances of io-pkt. The io-pkt manager will service mount requests of type io-pktX, where X is the instance number. For example:
io-pkt-v4-hc -i1 -ptcpip prefix=/alt
mount -Tio-pkt1 /lib/dll/
-P priority
The priority to use for io-pkt's main thread. The default is 21.
-p protocol [protocol_options]
The protocol to start, followed by a list of protocol-specific options.
Note: Use commas, not spaces, to separate the options.

The available protocols include:

Protocol Module
pf-v4 (for use with io-pkt-v4-hc)
pf-v6 (for use with io-pkt-v6-hc)
tcpip The stack includes TCP/IP; you need to specify this protocol only if you want to pass additional parameters (e.g., prefix=) to it. For more information about the options, see below.
-q interval
Set up the quiesce_all() watchdog. If unquiesce_all() isn't called within interval (1–5) seconds, io-pkt panics. The watchdog is disabled by default.
-r priority
The priority of the watchdog thread, which should be higher than the other io-pkt and socket application priorities. The default is 22.
Don't register a SIGSEGV handler to quiesce the hardware if a segmentation violation occurs. This can help with debugging if it isn't possible to get a backtrace to the original code that generated the SIGSEGV through the signal handler.
-t threads
The number of processing threads to create. By default, one thread is created per CPU. These threads are the packet-processing threads that operate at Layer2 and may become the stack thread. For more information, see the Overview chapter of the QNX Neutrino Core Networking User's Guide.
-U string
Specify the user and groups that io-pkt should drop to when you tell it to stop running as root (see below). The string can be in one of these forms:
  • uid[:gid[,sup_gid]*]
  • user_name[,sup_gid]*

The default is 99:99,120. In the second form, the primary group is the one specified for user_name in /etc/passwd.

The io-pkt manager drops to the user specified with the -U option when you issue the following sysctl command:

sysctl -w qnx.kern.droproot=value

The value is a hexadecimal number whose bits indicate which abilities io-pkt should keep, or 0 if you want io-pkt to continue to run as root. The QNX_DROPROOT_* flags are defined in <sys/iopkt_ability.h>:

Constant Value Ability
QNX_DROPROOT_STD 0x0001 Drop root without keeping any additional abilities (keep the “standard” ones listed below)
QNX_DROPROOT_PATHSPACE 0x0020 Not used; io-pkt keeps PROCMGR_AID_PATHSPACE by default

By default, io-pkt retains the following abilities:


For more information about abilities, see the entry for procmgr_ability() in the QNX Neutrino C Library Reference.

-u string
Specify the user, group, and access mode for the device nodes that io-pkt creates. Use the following format for string:



  • type is one of the following values: socket, bpf, pf, config, srt, tun, tap, llmcast, nraw, slip, pppmgr, altq, all.

    The all type sets the user ID, group ID, and mode combination for all of the possible device types.

  • uid and gid are either numeric, or the user or group name.
  • The mode value is an access mode in octal format (e.g., 0660 for read/write for user and group).
You can specify -u multiple times. Later instances override values set by earlier instances. For example, in the following command, the user ID, group ID, and access mode for the BPF device set using all in the first instance of -u is overriden by the values specified in the second instance:
io-pkt-v6-hc -u all,user1:iopkt,0660 -u bpf,user2:user2,0600  
-w interval
Set up the io-pkt watchdog. If the hardclock_ticks variable doesn't increase in interval (1–5) seconds, io-pkt panics. The watchdog is disabled by default.

TCP/IP options

If you specify the -p tcpip protocol, the protocol_options list can consist of one or more of the following, separated by commas without whitespace:

By default, the value of the pagesize option is used only for the mbuf and cluster pools; the other pools are of size sysconf(_SC_PAGESIZE). If you specify this option, the value of the pagesize option is used for all pools.
Use a larger stack size for the loading of drivers. Without this option, drivers are loaded using the default stacksize stack. With this option, a new larger stack is used. The default size of the larger stack is 128 KB, but you can specify a size, in bytes.
Disable the caching of packet buffers. This should be needed only as a debugging facility.
Monitor changes to configuration strings, in particular CS_HOSTNAME. By default, io-pkt gets the hostname once at startup.
Enable (1) or disable (0) fastforwarding path. This is useful for gateways. This option enables, and is enabled by, forward; to enable only forward, specify forward,fastforward=0.
Enable forwarding of IPv4 packets between interfaces; this enables fastforward by default. The default is off.
(io-pkt-v6-hc only) Enable forwarding of IPv6 packets between interfaces; off by default.
Reserve IPv4 identifier values, where X is between 2 and 8192, and a power of 2. When set, io-pkt does not use the IPv4 identifier values between 0 and X. Default is 0.
Enable IPsec support; off by default.
As mbufs are freed after use, rather than returning them to the internal pool for general consumption, up to X mbufs are cached per thread to allow quicker retrieval on the next allocation.
As mtags are freed after use, rather than returning them to the internal pool for general consumption, up to X mtags are cached per thread to allow quicker retrieval on the next allocation.

This applies only to tags of 16 bytes or less. The default number of tags cached is 128.

The mbuf cluster size. A cluster is the largest amount of contiguous memory used by an mbuf. If the MTU is larger than a cluster, multiple clusters are used to hold the packet. The default and minimum cluster size is 2 KB (to fit a standard 1500-byte Ethernet packet); the maximum is 64 KB or the value of the pagesize option, whichever is smaller. This value is rounded down to the nearest power of two.

Specifying the cluster size can improve performance; for more information, see Jumbo packets and hardware checksumming in the Network Drivers chapter of the QNX Neutrino Core Networking User's Guide.

Specify a semicolon-separated mapping of GIDs to Forwarding Information Bases (FIBs). For example, to map SGID 750 and 760 to FIBs 1 and 2, respectively, specify:
The number of pool caches created for mbuf and cluster pools. The default is 1 for each pool; the maximum is 20.
The maximum number of TAP interfaces that can be created. The default is 5. You can create TAP interfaces by either the /dev/tap cloning device, or via ifconfig's create command.
The number of TUN control interfaces (e.g., /dev/tun0) to create when io-pkt starts. The default is 4.

You can create TUN device interfaces (as listed by the ifconfig utility) by either opening a precreated control interface or using ifconfig create. The only way to create TUN device interfaces beyond the num_tun_control_interface number is to use ifconfig create.

The smallest amount of data allocated each time for the mbuf and cluster memory pools, or all pools if you specify bigpage_strict. This quantum is then carved into chunks of varying size, depending on the pool.

The default value is 128 KB, the maximum is 16 MB, and the minimum is sysconf(_SC_PAGESIZE). This value is rounded down to the nearest power of 2. This value also sets the maximum for mclbytes.

Run packet filters on packets before encryption. The default is to do it after encryption.
As mbuf and cluster combinations are freed after use, rather than return them to the internal pool for general consumption, up to X mbufs and clusters are cached per thread to allow quicker retrieval on the next allocation.
Allocate packet buffers from the specified typed memory object. For example:
io-pkt -ptcpip pkt_typed_mem=ram/dma
The path to prepend to the traditional /dev/socket. The is useful when running multiple stacks (see the -i option). Clients can target a particular stack by using the SOCK environment variable. For example:
io-pkt -i1 -ptcpip prefix=/alt
SOCK=/alt ifconfig -a
Specify the size of the receive context buffer, in bytes. The default is 65536; the minimum is 2048.
Specify the number of buffer objects that io-pkt can send in reply to an application in one kernel operation. This setting does not limit the amount of data that can be included in the reply, it just determines how many operations are needed to reply with a given amount of data. The default is 90 objects; the minimum is 32.
If using the SO_REUSEPORT socket option, received unicast UDP packets are delivered to all sockets bound to the port. The default is to deliver only multicast and broadcast to all sockets.
rx_prio=X or rx_pulse_prio=X
The priority for receive threads to use (the default is 21). A driver-specific priority option (if supported by the driver) can override this priority.
Specify whether or not support for the system memory management unit (IOMMU/SMMU) manager is required:
  • 0 or off — disable SMMU support. This is the default.
  • 1 or on — SMMU support is required; io-pkt exits if it isn't available

If value isn't valid, io-pkt disables SMMU support and sends a message to slogger2.

For more information, see the SMMUMAN User's Guide.

Enable the SO_TXPRIO socket option (see getsockopt() in the QNX Neutrino C Library Reference).

The SO_TXPRIO socket option sets the transmit queue priority on a socket. If you set this priority, then all traffic sent through the socket carries a packet tag of type PACKET_TAG_TXQ whose value is the priority value that you set with setsockopt(). If you don't start io-pkt with this option, and you then try to set SO_TXPRIO, setsockopt() fails and sets errno to EOPNOTSUPP.

The so_txprio_enable option restricts only the capability of the SO_TXPRIO socket option. It has no effect on, which can generate packets that carry PACKET_TAG_TXQ tags.

Note: Setting the so_txprio_enable option negatively affects the performance of io-pkt. This is true even if application code doesn't call setsockopt() to set the value of SO_TXPRIO. You should enable this option only if you need to set the transmit queue priority.

To complete the priority transmit queue function, a network driver must extract the priority value from the packet's PACKET_TAG_TXQ tag, and then enqueue the packet on the appropriate transmit queue. If a network driver doesn't support extracting PACKET_TAG_TXQ, then it can treat a packet as an ordinary one, and setting the SO_TXPRIO option has no useful effect, other than slowing down the traffic because of the extra work. Therefore application developers should use this option only with a network driver that supports priority transmit queues.

The io-pkt stack code (excluding network drivers) doesn't interpret this priority value in any way. Specifically, io-pkt doesn't associate the transmit queue priority with IP_TOS or IPV6_TCLASS. If you want to associate a transmit queue priority value with IP_TOS or IPV6_TCLASS, you must properly set both IP_TOS (or IPV6_TCLASS) and SO_TXPRIO on the socket, so that traffic through it has the proper type of service and is transmitted at the proper priority by a network driver.

Specify the value of SOMAXCONN, the maximum length of the listen queue used to accept new TCP connections. The minimum is the value in <sys/socket.h>.
Introduce a guard page between each thread's stack to aid in debugging “blown stack handling” panics. This will cause a SIGSEGV at the point of stack overrun rather than at the end of the operation.
Note: If the value of the stacksize option isn't a multiple of the system page size, then this option increases the stack size until it is. A message is logged to slogger2 in this case advising of the new size. This increase in stack size may change the issue being debugged.
Specify the size of each thread's stack, in bytes. The default is 4096 (4 KB) in 32-bit architectures, and 8192 (8 KB) in 64-bit architectures.
(QNX Neutrino 7.0.1 or later) Use the io-pkt timer for timestamping BPF. This results in a best-case precision of 1 millisecond, but the timestamps are guaranteed to be monotonic. By default ClockCycles() is used to give timestamps that are precise down to 1 microsecond, at the risk of occasional nonmonotonic timestamps as the ClockCycles() clock is recalibrated against the io-pkt timer.
If the supply of functional connections is exhausted, increment their number by this amount, up to the value of threads_max. The default is 25.
Note: The term “threads” in the TCP/IP threads_* options is a misnomer; it really refers to functional TCP/IP connections or blocking operations (read(), write(), accept(), etc.). It has nothing to do with the number of threads running in io-pkt-*.
Specify the maximum number of functional TCP/IP connections that the stack can service simultaneously. The default is 200.
Specify the minimum number of functional TCP/IP connections. The default is 15, and the minimum is 4.
The priority to use for the timer pulse. The default is 21.


Note: The High-Performance Networking Stack (io-sock) is available as an alternative to io-pkt. Systems can use io-pkt or io-sock, but not both. For more information, see the High-Performance Networking Stack User's Guide.

The io-pkt manager provides support for Internet domain sockets, Unix domain sockets, and dynamically loaded networking modules. It comes in the following stack variants:

IPv4 version of the stack that has full encryption and Wi-Fi capability built in and includes hardware-accelerated cryptography capability (Fast IPsec).
IPv6 version of the stack (includes IPv4 as part of v6) that has full encryption and Wi-Fi capability, also with hardware-accelerated cryptography.
Note: In order to use SSL connections, you must have started random with the -t option.

After you've launched io-pkt*, you can use the mount command to start drivers or load additional modules such as or If you want to pass options to the driver, use the -o option before the name of the shared object. For example:

mount -T io-pkt -o mac=12345678
  • You can't use umount to unmount io-pkt* drivers. You might be able to detach the driver from the stack by using ifconfig's destroy command (if the driver supports it).
  • If io-pkt runs out of threads, it sends a message to slogger2, and anything that requires a thread blocks until one becomes available.
  • The network drivers don't put entries into the /dev namespace, so a waitfor command for such an entry won't work properly in buildfiles or scripts. Use if_up -p instead; for example, if_up -p en0.
  • If a TCP/IP packet is smaller than the minimum Ethernet packet size, the packet may be padded with random data, rather than zeroes.

The io-pkt manager supports TUN and TAP. To create the interfaces, use ifconfig:

ifconfig tun0 create
ifconfig tap0 create

For more information, see the NetBSD documentation:

Generic driver options

The stack processes the following generic driver options:

Override the default interface prefix used for network drivers. For example:
io-pkt-v4-hc -d abc100 name=en

starts the fictitious driver with the “en” interface naming convention (enXX). You can also use this option to assign interface names based on (for example) functionality:

io-pkt-v4-hc -d abc100 pci=0,name=wan
The interface number to use. If number is negative, it's ignored. By default, the interfaces are numbered starting at 0.

The stack also processes the following driver options for all USB drivers using the NetBSD-to-QNX conversion library to let you identify a particular USB device using information obtained from running usb -v:

Device product ID.
Device vendor ID.
Device address, as reported by the usb utility.
Host controller, as reported by the usb utility

For example:

io-pkt-v4-hc -d abc100 did=0x0020,vid=0x13b1,devno=1,busno=1


Start the v6 variant of io-pkt using the fictitious driver:

io-pkt-v6-hc -d /lib/dll/ \
ifconfig abc0 10.184