PKTQUEUE(9) | Kernel Developer's Manual | PKTQUEUE(9)

# NAME

`pktqueue`, `pktq_create`, `pktq_destroy`, `pktq_enqueue`, `pktq_dequeue`, `pktq_barrier`, `pktq_ifdetach`, `pktq_flush`, `pktq_set_maxlen`, `pktq_rps_hash`, `pktq_sysctl_setup`, `sysctl_pktq_rps_hash_handler` — Lockless network protocol input queues with integrated ISR scheduling

# SYNOPSIS

`#include <net/pktqueue.h>`

pktqueue_t *
`pktq_create`(size_t maxlen, void (*intrh)(void *), void *arg);

void
`pktq_destroy`(pktqueue_t *pq);

bool
`pktq_enqueue`(pktqueue_t *pq, struct mbuf *m, u_int hash);

struct mbuf *
`pktq_dequeue`(pktqueue_t *pq);

void
`pktq_barrier`(pktqueue_t *pq);

void
`pktq_ifdetach`(void);

void
`pktq_flush`(pktqueue_t *pq);

int
`pktq_set_maxlen`(pktqueue_t *pq, size_t maxlen);

uint32_t
`pktq_rps_hash`(const pktq_rps_hash_func_t *funcp, const struct mbuf *m);

int
`pktq_sysctl_setup`(pktqueue_t *pq, struct sysctllog **clog, const struct sysctlnode *parent_node, int qid);

int
`sysctl_pktq_rps_hash_handler`(SYSCTLFN_ARGS);

# DESCRIPTION

The `pktqueue` functions provide a lockless network protocol input queue interface with integrated software interrupt scheduling and support for receiver-side packet steering (RPS). The implementation is based around per-CPU producer-consumer queues; multiple CPUs may enqueue packets into a CPU's queue, but only the owning CPU will dequeue packets from any given queue.

# FUNCTIONS

`pktq_create`(maxlen, intrh, arg)
  Create a packet queue that can store at most maxlen packets at one time. maxlen must not exceed `PCQ_MAXLEN`. The software interrupt handler intrh with argument arg will be established at `SOFTINT_NET`.
`pktq_destroy`(pq)
  Destroy the specified packet queue. The caller is responsible for ensuring that no packets remain in the queue prior to calling this function.
`pktq_enqueue`(pq, m, hash)
  Enqueue the packet m in the specified packet queue. The modulus of hash and the number of CPUs will be computed and used to select the per-CPU queue where the packet will be stored, and thus upon which CPU the packet will be processed. Once the CPU selection has been made and the packet placed in the queue, the software interrupt associated with packet queue will be scheduled.
`pktq_dequeue`(pq)
  Dequeue a packet from the current CPU's queue. If no packets remain, `NULL` is returned. This function must be called with kernel preemption disabled, which is always the case when running in a software interrupt handler.
`pktq_barrier`(pq)
  Wait for a grace period when all packets enqueued at the moment of calling this function will have been dequeued.
`pktq_ifdetach`()
  This function is called when a network interface is detached from the system. It performs a `pktq_barrier`() operation on all packet queues.
`pktq_flush`(pq)
  This function removes and frees all packets in the specified queue. The caller is responsible for ensuring that no calls to `pktq_enqueue`() or `pktq_dequeue`() run concurrently with `pktq_flush`().
`pktq_set_maxlen`(pq, maxlen)
  Sets the maximum queue length to the value maxlen. If the new value of maxlen is smaller than the previous value, then this routine may block until all packets that were previously in the packet queue can be re-enqueued.
`pktq_rps_hash`(funcp, m)
  Calculates the RPS hash for the packet m using the hash function referenced by funcp. The available hash functions are “zero” (always returns 0), “curcpu” (returns the index of the current CPU), “toeplitz” (Toeplitz hash of an IPv4 or IPv6 packet), and “toeplitz-othercpus” (same as “toeplitz” but always hashes to a CPU other than the current CPU). A default hash routine is provided by the global variable `pktq_rps_hash_default`. The default routine is guaranteed to be safe to use for any network protocol. The behavior of “toeplitz” and “toeplitz-othercpus” is undefined if used with protocols other than IPv4 or IPv6.
`pktq_sysctl_setup`(pq, clog, parent_node, qid)
  This function registers standard sysctl handlers for pq at the parent sysctl node parent_node. qid allows the caller to specify the node ID at which to attach to parent_node; use `CTL_CREATE` to dynamically assign a node ID. The clog argument is passed directly to `sysctl_createv`().
`sysctl_pktq_rps_hash_handler`()
  This function provides a way for the user to select the preferred RPS hash function to be used by a caller of `pktq_rps_hash`() via sysctl(8). When calling `sysctl_createv`() to create the sysctl node, pass `sysctl_pktq_rps_hash_handler`() as the func argument and the pointer to the RPS hash function reference variable as the newp argument (cast to ‘void *’).

# CODE REFERENCES

The `pktqueue` interface is implemented within the file net/pktqueue.c.

An example of how to use `pktq_rps_hash`() can be found in the `ether_input`() function. An example of how to use `sysctl_pktq_rps_hash_handler`() can be found in the `ether_sysctl_setup`() function. Both reside within the file net/if_ethersubr.c.

An example of how to use `pktq_sysctl_setup`() can be found in the `sysctl_net_inet_ip_setup`() function within the file netinet/ip_input.c.

# NOTES

The maxlen argument provided to `pktq_create`() specifies the maximum number of packets that can be stored in each per-CPU queue. This means that, in theory, the maximum number of packets that can be enqueued is ‘maxlen * ncpu’. However, as a practical matter, the number will be smaller because the distribution of packets across the per-CPU queues is not perfectly uniform.

Calls to `pktq_set_maxlen`() may result in re-ordering the delivery of packets currently in the queue.

# SEE ALSO

sysctl(8), kpreempt(9), pcq(9), softintr(9), sysctl(9)

# HISTORY

The `pktqueue` interface first appeared in NetBSD 7.0.

September 3, 2022 | NetBSD 11.0