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);
|
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
|
void
|
||||||
rte_eth_promiscuous_enable(uint8_t port_id)
|
rte_eth_promiscuous_enable(uint8_t port_id)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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);
|
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.
|
* The eth device event type for interrupt, and maybe others in the future.
|
||||||
*/
|
*/
|
||||||
|
@ -117,3 +117,13 @@ DPDK_2.2 {
|
|||||||
|
|
||||||
local: *;
|
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