szedata2: add scattered Rx

Add new RX function for handling scattered packets.

Signed-off-by: Matej Vido <matejvido@gmail.com>
This commit is contained in:
Matej Vido 2015-11-10 15:18:16 +01:00 committed by Thomas Monjalon
parent 906cea82aa
commit d992985ff3

View File

@ -358,6 +358,338 @@ eth_szedata2_rx(void *queue,
return num_rx;
}
static uint16_t
eth_szedata2_rx_scattered(void *queue,
struct rte_mbuf **bufs,
uint16_t nb_pkts)
{
unsigned int i;
struct rte_mbuf *mbuf;
struct szedata2_rx_queue *sze_q = queue;
struct rte_pktmbuf_pool_private *mbp_priv;
uint16_t num_rx = 0;
uint16_t buf_size;
uint16_t sg_size;
uint16_t hw_size;
uint16_t packet_size;
uint64_t num_bytes = 0;
struct szedata *sze = sze_q->sze;
uint8_t *header_ptr = NULL; /* header of packet */
uint8_t *packet_ptr1 = NULL;
uint8_t *packet_ptr2 = NULL;
uint16_t packet_len1 = 0;
uint16_t packet_len2 = 0;
uint16_t hw_data_align;
if (unlikely(sze_q->sze == NULL || nb_pkts == 0))
return 0;
/*
* Reads the given number of packets from szedata2 channel given
* by queue and copies the packet data into a newly allocated mbuf
* to return.
*/
for (i = 0; i < nb_pkts; i++) {
const struct szedata_lock *ct_rx_lck_backup;
unsigned int ct_rx_rem_bytes_backup;
unsigned char *ct_rx_cur_ptr_backup;
/* get the next sze packet */
if (sze->ct_rx_lck != NULL && !sze->ct_rx_rem_bytes &&
sze->ct_rx_lck->next == NULL) {
/* unlock old data */
szedata_rx_unlock_data(sze_q->sze, sze->ct_rx_lck_orig);
sze->ct_rx_lck_orig = NULL;
sze->ct_rx_lck = NULL;
}
/*
* Store items from sze structure which can be changed
* before mbuf allocating. Use these items in case of mbuf
* allocating failure.
*/
ct_rx_lck_backup = sze->ct_rx_lck;
ct_rx_rem_bytes_backup = sze->ct_rx_rem_bytes;
ct_rx_cur_ptr_backup = sze->ct_rx_cur_ptr;
if (!sze->ct_rx_rem_bytes && sze->ct_rx_lck_orig == NULL) {
/* nothing to read, lock new data */
sze->ct_rx_lck = szedata_rx_lock_data(sze_q->sze, ~0U);
sze->ct_rx_lck_orig = sze->ct_rx_lck;
/*
* Backup items from sze structure must be updated
* after locking to contain pointers to new locks.
*/
ct_rx_lck_backup = sze->ct_rx_lck;
ct_rx_rem_bytes_backup = sze->ct_rx_rem_bytes;
ct_rx_cur_ptr_backup = sze->ct_rx_cur_ptr;
if (sze->ct_rx_lck == NULL)
/* nothing to lock */
break;
sze->ct_rx_cur_ptr = sze->ct_rx_lck->start;
sze->ct_rx_rem_bytes = sze->ct_rx_lck->len;
if (!sze->ct_rx_rem_bytes)
break;
}
if (sze->ct_rx_rem_bytes < RTE_SZE2_PACKET_HEADER_SIZE) {
/*
* cut in header - copy parts of header to merge buffer
*/
if (sze->ct_rx_lck->next == NULL)
break;
/* copy first part of header */
rte_memcpy(sze->ct_rx_buffer, sze->ct_rx_cur_ptr,
sze->ct_rx_rem_bytes);
/* copy second part of header */
sze->ct_rx_lck = sze->ct_rx_lck->next;
sze->ct_rx_cur_ptr = sze->ct_rx_lck->start;
rte_memcpy(sze->ct_rx_buffer + sze->ct_rx_rem_bytes,
sze->ct_rx_cur_ptr,
RTE_SZE2_PACKET_HEADER_SIZE -
sze->ct_rx_rem_bytes);
sze->ct_rx_cur_ptr += RTE_SZE2_PACKET_HEADER_SIZE -
sze->ct_rx_rem_bytes;
sze->ct_rx_rem_bytes = sze->ct_rx_lck->len -
RTE_SZE2_PACKET_HEADER_SIZE +
sze->ct_rx_rem_bytes;
header_ptr = (uint8_t *)sze->ct_rx_buffer;
} else {
/* not cut */
header_ptr = (uint8_t *)sze->ct_rx_cur_ptr;
sze->ct_rx_cur_ptr += RTE_SZE2_PACKET_HEADER_SIZE;
sze->ct_rx_rem_bytes -= RTE_SZE2_PACKET_HEADER_SIZE;
}
sg_size = le16toh(*((uint16_t *)header_ptr));
hw_size = le16toh(*(((uint16_t *)header_ptr) + 1));
packet_size = sg_size -
RTE_SZE2_ALIGN8(RTE_SZE2_PACKET_HEADER_SIZE + hw_size);
/* checks if packet all right */
if (!sg_size)
errx(5, "Zero segsize");
/* check sg_size and hwsize */
if (hw_size > sg_size - RTE_SZE2_PACKET_HEADER_SIZE) {
errx(10, "Hwsize bigger than expected. Segsize: %d, "
"hwsize: %d", sg_size, hw_size);
}
hw_data_align =
RTE_SZE2_ALIGN8((RTE_SZE2_PACKET_HEADER_SIZE +
hw_size)) - RTE_SZE2_PACKET_HEADER_SIZE;
if (sze->ct_rx_rem_bytes >=
(uint16_t)(sg_size -
RTE_SZE2_PACKET_HEADER_SIZE)) {
/* no cut */
/* one packet ready - go to another */
packet_ptr1 = sze->ct_rx_cur_ptr + hw_data_align;
packet_len1 = packet_size;
packet_ptr2 = NULL;
packet_len2 = 0;
sze->ct_rx_cur_ptr += RTE_SZE2_ALIGN8(sg_size) -
RTE_SZE2_PACKET_HEADER_SIZE;
sze->ct_rx_rem_bytes -= RTE_SZE2_ALIGN8(sg_size) -
RTE_SZE2_PACKET_HEADER_SIZE;
} else {
/* cut in data */
if (sze->ct_rx_lck->next == NULL) {
errx(6, "Need \"next\" lock, but it is "
"missing: %u", sze->ct_rx_rem_bytes);
}
/* skip hw data */
if (sze->ct_rx_rem_bytes <= hw_data_align) {
uint16_t rem_size = hw_data_align -
sze->ct_rx_rem_bytes;
/* MOVE to next lock */
sze->ct_rx_lck = sze->ct_rx_lck->next;
sze->ct_rx_cur_ptr =
(void *)(((uint8_t *)
(sze->ct_rx_lck->start)) + rem_size);
packet_ptr1 = sze->ct_rx_cur_ptr;
packet_len1 = packet_size;
packet_ptr2 = NULL;
packet_len2 = 0;
sze->ct_rx_cur_ptr +=
RTE_SZE2_ALIGN8(packet_size);
sze->ct_rx_rem_bytes = sze->ct_rx_lck->len -
rem_size - RTE_SZE2_ALIGN8(packet_size);
} else {
/* get pointer and length from first part */
packet_ptr1 = sze->ct_rx_cur_ptr +
hw_data_align;
packet_len1 = sze->ct_rx_rem_bytes -
hw_data_align;
/* MOVE to next lock */
sze->ct_rx_lck = sze->ct_rx_lck->next;
sze->ct_rx_cur_ptr = sze->ct_rx_lck->start;
/* get pointer and length from second part */
packet_ptr2 = sze->ct_rx_cur_ptr;
packet_len2 = packet_size - packet_len1;
sze->ct_rx_cur_ptr +=
RTE_SZE2_ALIGN8(packet_size) -
packet_len1;
sze->ct_rx_rem_bytes = sze->ct_rx_lck->len -
(RTE_SZE2_ALIGN8(packet_size) -
packet_len1);
}
}
if (unlikely(packet_ptr1 == NULL))
break;
mbuf = rte_pktmbuf_alloc(sze_q->mb_pool);
if (unlikely(mbuf == NULL)) {
/*
* Restore items from sze structure to state after
* unlocking (eventually locking).
*/
sze->ct_rx_lck = ct_rx_lck_backup;
sze->ct_rx_rem_bytes = ct_rx_rem_bytes_backup;
sze->ct_rx_cur_ptr = ct_rx_cur_ptr_backup;
break;
}
/* get the space available for data in the mbuf */
mbp_priv = rte_mempool_get_priv(sze_q->mb_pool);
buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size -
RTE_PKTMBUF_HEADROOM);
if (packet_size <= buf_size) {
/* sze packet will fit in one mbuf, go ahead and copy */
rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
packet_ptr1, packet_len1);
if (packet_ptr2 != NULL) {
rte_memcpy((void *)
(rte_pktmbuf_mtod(mbuf, uint8_t *) +
packet_len1), packet_ptr2, packet_len2);
}
mbuf->data_len = (uint16_t)packet_size;
} else {
/*
* sze packet will not fit in one mbuf,
* scatter packet into more mbufs
*/
struct rte_mbuf *m = mbuf;
uint16_t len = rte_pktmbuf_tailroom(mbuf);
/* copy first part of packet */
/* fill first mbuf */
rte_memcpy(rte_pktmbuf_append(mbuf, len), packet_ptr1,
len);
packet_len1 -= len;
packet_ptr1 = ((uint8_t *)packet_ptr1) + len;
while (packet_len1 > 0) {
/* fill new mbufs */
m->next = rte_pktmbuf_alloc(sze_q->mb_pool);
if (unlikely(m->next == NULL)) {
rte_pktmbuf_free(mbuf);
/*
* Restore items from sze structure
* to state after unlocking (eventually
* locking).
*/
sze->ct_rx_lck = ct_rx_lck_backup;
sze->ct_rx_rem_bytes =
ct_rx_rem_bytes_backup;
sze->ct_rx_cur_ptr =
ct_rx_cur_ptr_backup;
goto finish;
}
m = m->next;
len = RTE_MIN(rte_pktmbuf_tailroom(m),
packet_len1);
rte_memcpy(rte_pktmbuf_append(mbuf, len),
packet_ptr1, len);
(mbuf->nb_segs)++;
packet_len1 -= len;
packet_ptr1 = ((uint8_t *)packet_ptr1) + len;
}
if (packet_ptr2 != NULL) {
/* copy second part of packet, if exists */
/* fill the rest of currently last mbuf */
len = rte_pktmbuf_tailroom(m);
rte_memcpy(rte_pktmbuf_append(mbuf, len),
packet_ptr2, len);
packet_len2 -= len;
packet_ptr2 = ((uint8_t *)packet_ptr2) + len;
while (packet_len2 > 0) {
/* fill new mbufs */
m->next = rte_pktmbuf_alloc(
sze_q->mb_pool);
if (unlikely(m->next == NULL)) {
rte_pktmbuf_free(mbuf);
/*
* Restore items from sze
* structure to state after
* unlocking (eventually
* locking).
*/
sze->ct_rx_lck =
ct_rx_lck_backup;
sze->ct_rx_rem_bytes =
ct_rx_rem_bytes_backup;
sze->ct_rx_cur_ptr =
ct_rx_cur_ptr_backup;
goto finish;
}
m = m->next;
len = RTE_MIN(rte_pktmbuf_tailroom(m),
packet_len2);
rte_memcpy(
rte_pktmbuf_append(mbuf, len),
packet_ptr2, len);
(mbuf->nb_segs)++;
packet_len2 -= len;
packet_ptr2 = ((uint8_t *)packet_ptr2) +
len;
}
}
}
mbuf->pkt_len = packet_size;
mbuf->port = sze_q->in_port;
bufs[num_rx] = mbuf;
num_rx++;
num_bytes += packet_size;
}
finish:
sze_q->rx_pkts += num_rx;
sze_q->rx_bytes += num_bytes;
return num_rx;
}
static uint16_t
eth_szedata2_tx(void *queue,
struct rte_mbuf **bufs,
@ -860,8 +1192,16 @@ eth_dev_stop(struct rte_eth_dev *dev)
}
static int
eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
eth_dev_configure(struct rte_eth_dev *dev)
{
struct rte_eth_dev_data *data = dev->data;
if (data->dev_conf.rxmode.enable_scatter == 1) {
dev->rx_pkt_burst = eth_szedata2_rx_scattered;
data->scattered_rx = 1;
} else {
dev->rx_pkt_burst = eth_szedata2_rx;
data->scattered_rx = 0;
}
return 0;
}
@ -1141,12 +1481,15 @@ rte_eth_from_szedata2(const char *name,
{
struct pmd_internals *internals = NULL;
struct rte_eth_dev *eth_dev = NULL;
struct rte_eth_dev_data *data = NULL;
int ret;
if (rte_pmd_init_internals(name, 0, 0, numa_node,
&internals, &eth_dev) < 0)
return -1;
data = eth_dev->data;
internals->sze_dev = szedata2->sze_dev;
internals->sze_rx_req = szedata2->sze_rx_mask_req;
internals->sze_tx_req = szedata2->sze_tx_mask_req;
@ -1171,7 +1514,14 @@ rte_eth_from_szedata2(const char *name,
return -1;
}
eth_dev->rx_pkt_burst = eth_szedata2_rx;
if (data->dev_conf.rxmode.enable_scatter == 1 ||
data->scattered_rx == 1) {
eth_dev->rx_pkt_burst = eth_szedata2_rx_scattered;
data->scattered_rx = 1;
} else {
eth_dev->rx_pkt_burst = eth_szedata2_rx;
data->scattered_rx = 0;
}
eth_dev->tx_pkt_burst = eth_szedata2_tx;
return 0;