ethdev: add buffered Tx
Many sample apps include internal buffering for single-packet-at-a-time operation. Since this is such a common paradigm, this functionality is better suited to being implemented in the ethdev API. The new APIs in the ethdev library are: * rte_eth_tx_buffer_init - initialize buffer * rte_eth_tx_buffer - buffer up a single packet for future transmission * rte_eth_tx_buffer_flush - flush any unsent buffered packets * rte_eth_tx_buffer_set_err_callback - set up a callback to be called in case transmitting a buffered burst fails. By default, we just free the unsent packets. As well as these, an additional reference callbacks are provided, which frees the packets: * rte_eth_tx_buffer_drop_callback - silently drop packets (default behavior) * rte_eth_tx_buffer_count_callback - drop and update user-provided counter to track the number of dropped packets Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com> Acked-by: Thomas Monjalon <thomas.monjalon@6wind.com>
This commit is contained in:
parent
fd2fca6f6b
commit
d6c99e62c8
@ -1270,6 +1270,52 @@ rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id,
|
||||
socket_id, tx_conf);
|
||||
}
|
||||
|
||||
void
|
||||
rte_eth_tx_buffer_drop_callback(struct rte_mbuf **pkts, uint16_t unsent,
|
||||
void *userdata __rte_unused)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < unsent; i++)
|
||||
rte_pktmbuf_free(pkts[i]);
|
||||
}
|
||||
|
||||
void
|
||||
rte_eth_tx_buffer_count_callback(struct rte_mbuf **pkts, uint16_t unsent,
|
||||
void *userdata)
|
||||
{
|
||||
uint64_t *count = userdata;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < unsent; i++)
|
||||
rte_pktmbuf_free(pkts[i]);
|
||||
|
||||
*count += unsent;
|
||||
}
|
||||
|
||||
int
|
||||
rte_eth_tx_buffer_set_err_callback(struct rte_eth_dev_tx_buffer *buffer,
|
||||
buffer_tx_error_fn cbfn, void *userdata)
|
||||
{
|
||||
buffer->error_callback = cbfn;
|
||||
buffer->error_userdata = userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rte_eth_tx_buffer_init(struct rte_eth_dev_tx_buffer *buffer, uint16_t size)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
buffer->size = size;
|
||||
if (buffer->error_callback == NULL)
|
||||
rte_eth_tx_buffer_set_err_callback(buffer,
|
||||
rte_eth_tx_buffer_drop_callback, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rte_eth_promiscuous_enable(uint8_t port_id)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -2655,6 +2655,210 @@ rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id,
|
||||
return (*dev->tx_pkt_burst)(dev->data->tx_queues[queue_id], tx_pkts, nb_pkts);
|
||||
}
|
||||
|
||||
typedef void (*buffer_tx_error_fn)(struct rte_mbuf **unsent, uint16_t count,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* Structure used to buffer packets for future TX
|
||||
* Used by APIs rte_eth_tx_buffer and rte_eth_tx_buffer_flush
|
||||
*/
|
||||
struct rte_eth_dev_tx_buffer {
|
||||
buffer_tx_error_fn error_callback;
|
||||
void *error_userdata;
|
||||
uint16_t size; /**< Size of buffer for buffered tx */
|
||||
uint16_t length; /**< Number of packets in the array */
|
||||
struct rte_mbuf *pkts[];
|
||||
/**< Pending packets to be sent on explicit flush or when full */
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the size of the tx buffer.
|
||||
*
|
||||
* @param sz
|
||||
* Number of stored packets.
|
||||
*/
|
||||
#define RTE_ETH_TX_BUFFER_SIZE(sz) \
|
||||
(sizeof(struct rte_eth_dev_tx_buffer) + (sz) * sizeof(struct rte_mbuf *))
|
||||
|
||||
/**
|
||||
* Initialize default values for buffered transmitting
|
||||
*
|
||||
* @param buffer
|
||||
* Tx buffer to be initialized.
|
||||
* @param size
|
||||
* Buffer size
|
||||
* @return
|
||||
* 0 if no error
|
||||
*/
|
||||
int
|
||||
rte_eth_tx_buffer_init(struct rte_eth_dev_tx_buffer *buffer, uint16_t size);
|
||||
|
||||
/**
|
||||
* Send any packets queued up for transmission on a port and HW queue
|
||||
*
|
||||
* This causes an explicit flush of packets previously buffered via the
|
||||
* rte_eth_tx_buffer() function. It returns the number of packets successfully
|
||||
* sent to the NIC, and calls the error callback for any unsent packets. Unless
|
||||
* explicitly set up otherwise, the default callback simply frees the unsent
|
||||
* packets back to the owning mempool.
|
||||
*
|
||||
* @param port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param queue_id
|
||||
* The index of the transmit queue through which output packets must be
|
||||
* sent.
|
||||
* The value must be in the range [0, nb_tx_queue - 1] previously supplied
|
||||
* to rte_eth_dev_configure().
|
||||
* @param buffer
|
||||
* Buffer of packets to be transmit.
|
||||
* @return
|
||||
* The number of packets successfully sent to the Ethernet device. The error
|
||||
* callback is called for any packets which could not be sent.
|
||||
*/
|
||||
static inline uint16_t
|
||||
rte_eth_tx_buffer_flush(uint8_t port_id, uint16_t queue_id,
|
||||
struct rte_eth_dev_tx_buffer *buffer)
|
||||
{
|
||||
uint16_t sent;
|
||||
uint16_t to_send = buffer->length;
|
||||
|
||||
if (to_send == 0)
|
||||
return 0;
|
||||
|
||||
sent = rte_eth_tx_burst(port_id, queue_id, buffer->pkts, to_send);
|
||||
|
||||
buffer->length = 0;
|
||||
|
||||
/* All packets sent, or to be dealt with by callback below */
|
||||
if (unlikely(sent != to_send))
|
||||
buffer->error_callback(&buffer->pkts[sent], to_send - sent,
|
||||
buffer->error_userdata);
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer a single packet for future transmission on a port and queue
|
||||
*
|
||||
* This function takes a single mbuf/packet and buffers it for later
|
||||
* transmission on the particular port and queue specified. Once the buffer is
|
||||
* full of packets, an attempt will be made to transmit all the buffered
|
||||
* packets. In case of error, where not all packets can be transmitted, a
|
||||
* callback is called with the unsent packets as a parameter. If no callback
|
||||
* is explicitly set up, the unsent packets are just freed back to the owning
|
||||
* mempool. The function returns the number of packets actually sent i.e.
|
||||
* 0 if no buffer flush occurred, otherwise the number of packets successfully
|
||||
* flushed
|
||||
*
|
||||
* @param port_id
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param queue_id
|
||||
* The index of the transmit queue through which output packets must be
|
||||
* sent.
|
||||
* The value must be in the range [0, nb_tx_queue - 1] previously supplied
|
||||
* to rte_eth_dev_configure().
|
||||
* @param buffer
|
||||
* Buffer used to collect packets to be sent.
|
||||
* @param tx_pkt
|
||||
* Pointer to the packet mbuf to be sent.
|
||||
* @return
|
||||
* 0 = packet has been buffered for later transmission
|
||||
* N > 0 = packet has been buffered, and the buffer was subsequently flushed,
|
||||
* causing N packets to be sent, and the error callback to be called for
|
||||
* the rest.
|
||||
*/
|
||||
static inline uint16_t __attribute__((always_inline))
|
||||
rte_eth_tx_buffer(uint8_t port_id, uint16_t queue_id,
|
||||
struct rte_eth_dev_tx_buffer *buffer, struct rte_mbuf *tx_pkt)
|
||||
{
|
||||
buffer->pkts[buffer->length++] = tx_pkt;
|
||||
if (buffer->length < buffer->size)
|
||||
return 0;
|
||||
|
||||
return rte_eth_tx_buffer_flush(port_id, queue_id, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a callback for buffered packets which cannot be sent
|
||||
*
|
||||
* Register a specific callback to be called when an attempt is made to send
|
||||
* all packets buffered on an ethernet port, but not all packets can
|
||||
* successfully be sent. The callback registered here will be called only
|
||||
* from calls to rte_eth_tx_buffer() and rte_eth_tx_buffer_flush() APIs.
|
||||
* The default callback configured for each queue by default just frees the
|
||||
* packets back to the calling mempool. If additional behaviour is required,
|
||||
* for example, to count dropped packets, or to retry transmission of packets
|
||||
* which cannot be sent, this function should be used to register a suitable
|
||||
* callback function to implement the desired behaviour.
|
||||
* The example callback "rte_eth_count_unsent_packet_callback()" is also
|
||||
* provided as reference.
|
||||
*
|
||||
* @param buffer
|
||||
* The port identifier of the Ethernet device.
|
||||
* @param callback
|
||||
* The function to be used as the callback.
|
||||
* @param userdata
|
||||
* Arbitrary parameter to be passed to the callback function
|
||||
* @return
|
||||
* 0 on success, or -1 on error with rte_errno set appropriately
|
||||
*/
|
||||
int
|
||||
rte_eth_tx_buffer_set_err_callback(struct rte_eth_dev_tx_buffer *buffer,
|
||||
buffer_tx_error_fn callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Callback function for silently dropping unsent buffered packets.
|
||||
*
|
||||
* This function can be passed to rte_eth_tx_buffer_set_err_callback() to
|
||||
* adjust the default behavior when buffered packets cannot be sent. This
|
||||
* function drops any unsent packets silently and is used by tx buffered
|
||||
* operations as default behavior.
|
||||
*
|
||||
* NOTE: this function should not be called directly, instead it should be used
|
||||
* as a callback for packet buffering.
|
||||
*
|
||||
* NOTE: when configuring this function as a callback with
|
||||
* rte_eth_tx_buffer_set_err_callback(), the final, userdata parameter
|
||||
* should point to an uint64_t value.
|
||||
*
|
||||
* @param pkts
|
||||
* The previously buffered packets which could not be sent
|
||||
* @param unsent
|
||||
* The number of unsent packets in the pkts array
|
||||
* @param userdata
|
||||
* Not used
|
||||
*/
|
||||
void
|
||||
rte_eth_tx_buffer_drop_callback(struct rte_mbuf **pkts, uint16_t unsent,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* Callback function for tracking unsent buffered packets.
|
||||
*
|
||||
* This function can be passed to rte_eth_tx_buffer_set_err_callback() to
|
||||
* adjust the default behavior when buffered packets cannot be sent. This
|
||||
* function drops any unsent packets, but also updates a user-supplied counter
|
||||
* to track the overall number of packets dropped. The counter should be an
|
||||
* uint64_t variable.
|
||||
*
|
||||
* NOTE: this function should not be called directly, instead it should be used
|
||||
* as a callback for packet buffering.
|
||||
*
|
||||
* NOTE: when configuring this function as a callback with
|
||||
* rte_eth_tx_buffer_set_err_callback(), the final, userdata parameter
|
||||
* should point to an uint64_t value.
|
||||
*
|
||||
* @param pkts
|
||||
* The previously buffered packets which could not be sent
|
||||
* @param unsent
|
||||
* The number of unsent packets in the pkts array
|
||||
* @param userdata
|
||||
* Pointer to an uint64_t value, which will be incremented by unsent
|
||||
*/
|
||||
void
|
||||
rte_eth_tx_buffer_count_callback(struct rte_mbuf **pkts, uint16_t unsent,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* The eth device event type for interrupt, and maybe others in the future.
|
||||
*/
|
||||
|
@ -117,3 +117,13 @@ DPDK_2.2 {
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
||||
DPDK_16.04 {
|
||||
global:
|
||||
|
||||
rte_eth_tx_buffer_count_callback;
|
||||
rte_eth_tx_buffer_drop_callback;
|
||||
rte_eth_tx_buffer_init;
|
||||
rte_eth_tx_buffer_set_err_callback;
|
||||
|
||||
} DPDK_2.2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user