Skip site navigation (1)Skip section navigation (2)

FreeBSD Man Pages

Man Page or Keyword Search:
Man Architecture
Apropos Keyword Search (all sections) Output format
home | help
NETMAP(4)              FreeBSD Kernel Interfaces Manual              NETMAP(4)

     netmap - a framework for fast packet I/O

     device netmap

     netmap is a framework for fast and safe access to network devices
     (reaching 14.88 Mpps at less than 1 GHz).  netmap uses memory mapped
     buffers and metadata (buffer indexes and lengths) to communicate with the
     kernel, which is in charge of validating information through ioctl() and
     select()/poll().  netmap can exploit the parallelism in multiqueue
     devices and multicore systems.

     netmap requires explicit support in device drivers.  For a list of
     supported devices, see the end of this manual page.

     netmap clients must first open the open("/dev/netmap"), and then issue an
     ioctl(...,NIOCREGIF,...) to bind the file descriptor to a network device.

     When a device is put in netmap mode, its data path is disconnected from
     the host stack.  The processes owning the file descriptor can exchange
     packets with the device, or with the host stack, through an mmapped
     memory region that contains pre-allocated buffers and metadata.

     Non blocking I/O is done with special ioctl()'s, whereas the file
     descriptor can be passed to select()/poll() to be notified about incoming
     packet or available transmit buffers.

   Data structures
     All data structures for all devices in netmap mode are in a memory region
     shared by the kernel and all processes who open /dev/netmap (NOTE:
     visibility may be restricted in future implementations).  All references
     between the shared data structure are relative (offsets or indexes). Some
     macros help converting them into actual pointers.

     The data structures in shared memory are the following:

     struct netmap_if (one per interface)
          indicates the number of rings supported by an interface, their
          sizes, and the offsets of the netmap_rings associated to the
          interface.  The offset of a struct netmap_if in the shared memory
          region is indicated by the nr_offset field in the structure returned
          by the NIOCREGIF (see below).

          struct netmap_if {
              char ni_name[IFNAMSIZ]; /* name of the interface. */
              const u_int ni_num_queues; /* number of hw ring pairs */
              const ssize_t   ring_ofs[]; /* offset of tx and rx rings */

     struct netmap_ring (one per ring)
          contains the index of the current read or write slot (cur), the
          number of slots available for reception or transmission (avail), and
          an array of slots describing the buffers.  There is one ring pair
          for each of the N hardware ring pairs supported by the card
          (numbered 0..N-1), plus one ring pair (numbered N) for packets
          from/to the host stack.

          struct netmap_ring {
              const ssize_t buf_ofs;
              const uint32_t num_slots; /* number of slots in the ring. */
              uint32_t avail; /* number of usable slots */
              uint32_t cur; /* 'current' index for the user side */

              const uint16_t nr_buf_size;
              uint16_t flags;
              struct netmap_slot slot[0]; /* array of slots. */

     struct netmap_slot (one per packet)
          contains the metadata for a packet: a buffer index (buf_idx), a
          buffer length (len), and some flags.

          struct netmap_slot {
              uint32_t buf_idx; /* buffer index */
              uint16_t len;   /* packet length */
              uint16_t flags; /* buf changed, etc. */
          #define NS_BUF_CHANGED  0x0001  /* must resync, buffer changed */
          #define NS_REPORT       0x0002  /* tell hw to report results
                                           * e.g. by generating an interrupt

     packet buffers
          are fixed size (approximately 2k) buffers allocated by the kernel
          that contain packet data. Buffers addresses are computed through

     Some macros support the access to objects in the shared memory region. In

     struct netmap_if *nifp;
     struct netmap_ring *txring = NETMAP_TXRING(nifp, i);
     struct netmap_ring *rxring = NETMAP_RXRING(nifp, i);
     int i = txring->slot[txring->cur].buf_idx;
     char *buf = NETMAP_BUF(txring, i);

     netmap supports some ioctl() to synchronize the state of the rings
     between the kernel and the user processes, plus some to query and
     configure the interface.  The former do not require any argument, whereas
     the latter use a struct netmap_req defined as follows:

     struct nmreq {
             char      nr_name[IFNAMSIZ];
             uint32_t  nr_offset;      /* nifp offset in the shared region */
             uint32_t  nr_memsize;     /* size of the shared region */
             uint32_t  nr_numdescs;    /* descriptors per queue */
             uint16_t  nr_numqueues;
             uint16_t  nr_ringid;      /* ring(s) we care about */
     #define NETMAP_HW_RING  0x4000    /* low bits indicate one hw ring */
     #define NETMAP_SW_RING  0x2000    /* we process the sw ring */
     #define NETMAP_NO_TX_POLL 0x1000  /* no gratuitous txsync on poll */
     #define NETMAP_RING_MASK 0xfff    /* the actual ring number */

     A device descriptor obtained through /dev/netmap also supports the ioctl
     supported by network devices.

     The netmap-specific ioctl(2) command codes below are defined in
     <net/netmap.h> and are:

           returns information about the interface named in nr_name.  On
           return, nr_memsize indicates the size of the shared netmap memory
           region (this is device-independent), nr_numslots indicates how many
           buffers are in a ring, nr_numrings indicates the number of rings
           supported by the hardware.

           If the device does not support netmap, the ioctl returns EINVAL.

           puts the interface named in nr_name into netmap mode, disconnecting
           it from the host stack, and/or defines which rings are controlled
           through this file descriptor.  On return, it gives the same info as
           NIOCGINFO, and nr_ringid indicates the identity of the rings
           controlled through the file descriptor.

           Possible values for nr_ringid are

           0      default, all hardware rings

                  the ``host rings'' connecting to the host stack

           NETMAP_HW_RING + i
                  the i-th hardware ring
           By default, a poll or select call pushes out any pending packets on
           the transmit ring, even if no write events are specified.  The
           feature can be disabled by or-ing NETMAP_NO_TX_SYNC to nr_ringid.
           But normally you should keep this feature unless you are using
           separate file descriptors for the send and receive rings, because
           otherwise packets are pushed out only if NETMAP_TXSYNC is called,
           or the send queue is full.

           NIOCREGIF can be used multiple times to change the association of a
           file descriptor to a ring pair, always within the same device.

           brings an interface back to normal mode.

           tells the hardware of new packets to transmit, and updates the
           number of slots available for transmission.

           tells the hardware of consumed packets, and asks for newly
           available packets.

     netmap uses select and poll to wake up processes when significant events

     The following code implements a traffic generator

     #include <net/netmap.h>
     #include <net/netmap_user.h>
     struct netmap_if *nifp;
     struct netmap_ring *ring;
     struct netmap_request nmr;

     fd = open("/dev/netmap", O_RDWR);
     bzero(&nmr, sizeof(nmr));
     strcpy(nmr.nm_name, "ix0");
     ioctl(fd, NIOCREG, &nmr);
     p = mmap(0, nmr.memsize, fd);
     nifp = NETMAP_IF(p, nmr.offset);
     ring = NETMAP_TXRING(nifp, 0);
     fds.fd = fd; = POLLOUT;
     for (;;) {
         poll(list, 1, -1);
         while (ring->avail-- > 0) {
             i = ring->cur;
             buf = NETMAP_BUF(ring, ring->slot[i].buf_index);
             ... prepare packet in buf ...
             ring->slot[i].len = ... packet length ...
             ring->cur = NETMAP_RING_NEXT(ring, i);

     netmap supports the following interfaces: em(4), ixgbe(4), re(4),

     The netmap framework has been designed and implemented by Luigi Rizzo and
     Matteo Landi in 2011 at the Universita` di Pisa.

FreeBSD 11.0-PRERELEASE        November 16, 2011       FreeBSD 11.0-PRERELEASE


Want to link to this manual page? Use this URL:

home | help