NDP API

This part of the libnfb library is used to access high-speed queues for packet transmissions.

Basic structures

struct ndp_packet

NDP packet.

NDP packet contains packet data and metadata (header).

Warning

The data are not allocated when this ‘struct’ is created, they are still in their original locations, so proper care must be taken when working with NDP packets (especially, one must NOT assume that the data is available as long as this ‘struct’ is available).

Public Members

unsigned char *data

Packet data location.

uint32_t data_length

Packet data length.

uint16_t flags

Packet specific flags.

unsigned char *header

Packet metadata location.

uint16_t header_length

Packet metadata length.

Init and deinit functions

ndp_rx_queue_t *ndp_open_rx_queue(struct nfb_device *nfb, unsigned queue_id)

Open (subscribe) NDP RX queue.

Parameters:
  • nfb[in] NFB device

  • queue_id[in] Queue ID

Returns:

NDP RX queue datatype on success, NULL on error

ndp_tx_queue_t *ndp_open_tx_queue(struct nfb_device *nfb, unsigned queue_id)

Open (subscribe) NDP TX queue.

Parameters:
  • nfb[in] NFB device

  • queue_id[in] Queue ID

Returns:

NDP TX queue datatype on success, NULL on error

void ndp_close_rx_queue(ndp_rx_queue_t *queue)

Close (unsubscribe) NDP RX queue.

The queue must not be used after this function is called and should be set to NULL by the application.

Parameters:

queue[in] NDP RX queue

void ndp_close_tx_queue(ndp_tx_queue_t *queue)

Close (unsubscribe) NDP TX queue.

The queue must not be used after this function is called and should be set to NULL by the application.

Parameters:

queue[in] NDP TX queue

Transmission functions

int ndp_queue_start(struct ndp_queue *queue)

Start traffic on queue.

When this function is called, RX queue become able to receive packets (don’t mistake this with RXMAC control), or TX queue become able to transmit packets.

Parameters:

queue[in] NDP queue

Returns:

NDP_OK on success, nonzero error code otherwise

int ndp_queue_stop(struct ndp_queue *queue)

Stop traffic on queue.

When this function is called, it stops the delivery of packets to the queue.

Parameters:

queue[in] NDP queue

Returns:

NDP_OK on success, nonzero error code otherwise

unsigned ndp_rx_burst_get(ndp_rx_queue_t *queue, struct ndp_packet *packets, unsigned count)

Get (read) burst of NDP packets from NDP RX queue.

When the function returns nonzero, the NDP packet structs in packets are filled with pointers to packet data. This data is valid until ndp_rx_burst_put is called.

The packet data must eventually be released through ndp_rx_burst_put. The usage should look like this

struct ndp_packet packets[32];
unsigned count = 32;
struct ndp_packet more_packets[16];
unsigned more_count = 16;

while (!STOPPED) {
  unsigned nb_rx = ndp_rx_burst_get(queue, packets, count);
  // process packets
  if (condition) {
    nb_rx += ndp_rx_burst_get(queue, more_packets, more_count); // this is OK
    // process more packets
  }
  ndp_rx_burst_put(queue); // but this should be called "soon enough"
}

Note

Traffic must be started (see ndp_queue_start)

Parameters:
  • queue[in] NDP RX queue

  • packets[out] Array of NDP packet structs

  • count[in] Maximal count of packets to read (length of packets)

Returns:

Count of actually read packets

void ndp_rx_burst_put(ndp_rx_queue_t *queue)

Put back (end reading) bursts of NDP packets from NDP queue.

This function should be called when the application has finished processing the packets obtained by previous ndp_rx_burst_get on the same queue. The amount of data available for processing is limited, so this function should best be called after every ndp_rx_burst_get.

See also

ndp_rx_burst_get for an example how to use this API.

Parameters:

queue[in] NDP RX queue

unsigned ndp_tx_burst_get(ndp_tx_queue_t *queue, struct ndp_packet *packets, unsigned count)

Get burst of packet placeholders from NDP TX queue.

This function allocates NDP frame placeholders in the TX queue and sets the pointers to them to the structs in packets parameter. To do this, the user MUST fill the ndp_packet::data_length field of the structs in packets and MUST NOT fill the ndp_packet::data field, as the pointer is invalid and will be usable after the function returns successfully.

The user is expected to fill the required data lengths in the packets array, call this function to allocate placeholders, fill placeholders with packet data and finally call ndp_tx_burst_put to send the burst.

API example:

struct ndp_packet rx_packets[32], tx_packets[32];
unsigned count = 32;

while (!STOPPED) {
  unsigned nb_rx = nb_rx_burst_get(rx_queue, rx_packets, count);

  // fill structs with requested packet lengths
  for(int i = 0; i < nb_rx; i++) {
    tx_packets[i].data_length = rx_packets[i].data_length;
  }

  // get placeholders of requested lengths
  unsigned nb_tx = nb_tx_burst_get(tx_queue, tx_packets, nb_rx);

  // write data to placeholders
  for(int i = 0; i < nb_tx; i++) {
    memcpy(tx_packets[i].data, rx_packets[i].data, tx_packets[i].data_len);
  }

  nb_tx_burst_put(tx_queue);
  nb_rx_burst_put(rx_queue);
}

Parameters:
  • queue[in] NDP TX queue

  • packets[inout] NDP packet structs with only sizes filled

  • count[in] Maximal count of retrieved placeholders (length of packets)

Returns:

Count of actually retrieved placeholders. Current implemenation returns either requested count or zero; no values in between.

void ndp_tx_burst_put(ndp_tx_queue_t *queue)

Put back (write) bursts of NDP packets to NDP TX queue.

This function must be called after (1 or more) call to ndp_tx_burst_get to notify the library that the bursts were processed and can be written.

See ndp_rx_burst_put for the API usage and caveats.

Also be aware, that the library tries to hold NDP packets for best performance, thus they doesn’t have to be send immediately. See ndp_tx_burst_flush.

Parameters:

queue[in] NDP TX queue

unsigned ndp_tx_burst_copy(ndp_tx_queue_t *queue, struct ndp_packet *packets, unsigned count)

Write a burst of NDP packets to NDP TX queue with data copying.

This is the slower but simpler way to transmit data. The structs in packets must contain full packet information, the data (and metadata) will be copied from the packets to the NDP buffer.

API example:

struct ndp_packet packets[32];
unsigned count = 32;

while (!STOPPED) {
    unsigned nb_rx = ndp_rx_burst_get(rx_queue, packets, count);
    // process packets
    unsigned nb_tx = ndp_tx_burst_copy(tx_queue, packets, nb_rx);
}

Parameters:
  • queue[in] NDP TX queue

  • packets[in] NDP packet structs filled with packet data

  • count[in] Count of packets to write

Returns:

Count of actually written packets

Miscellaneous functions

int ndp_queue_get_numa_node(const struct ndp_queue *queue)

Get number of NDP queue NUMA node.

Parameters:

queue[in] NDP queue

Returns:

NUMA node number on success, negative error code otherwise