@@ -38,10 +38,6 @@ typedef struct {
size_t frame_offset; /* offset from start of pkt buf */
size_t buf_size; /* size of buffer payload in 'pool' */
struct nm_desc *desc; /* netmap meta-data for the device */
- uint32_t begin;
- uint32_t end;
- struct netmap_ring *rxring;
- struct netmap_ring *txring;
odp_queue_t tx_access; /* exclusive access to send packets */
uint32_t if_flags;
netmap_dev_t *nm_dev;
@@ -64,6 +64,12 @@ static odp_spinlock_t nm_global_lock;
static netmap_dev_t netmap_devs[MAX_DEVS];
static int nm_dev_cnt;
+struct dispatch_args {
+ odp_packet_t *pkt_table;
+ unsigned nb_rx;
+ pkt_netmap_t *pkt_nm;
+};
+
int odp_netmap_init_global(void)
{
odp_spinlock_init(&nm_global_lock);
@@ -198,11 +204,6 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
odp_thread_id(),
pkt_nm->desc->mem);
- pkt_nm->begin = 0;
- pkt_nm->end = pkt_nm->desc->req.nr_rx_rings;
- pkt_nm->rxring = NETMAP_RXRING(pkt_nm->desc->nifp, 0);
- pkt_nm->txring = NETMAP_TXRING(pkt_nm->desc->nifp, 0);
-
ret = nm_do_ioctl(pkt_nm, SIOCGIFFLAGS, 0);
if (ret)
return ret;
@@ -256,173 +257,96 @@ int close_pkt_netmap(pkt_netmap_t * const pkt_nm)
return 0;
}
-int recv_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
- unsigned len)
+static void nm_recv_cb(uint8_t *arg, const struct nm_pkthdr *hdr,
+ const uint8_t *buf)
{
- struct netmap_ring *rxring = pkt_nm->rxring;
- int fd;
- unsigned nb_rx = 0;
- uint32_t limit, rx;
- uint32_t ringid = pkt_nm->begin;
- odp_packet_t pkt = ODP_PACKET_INVALID;
- struct pollfd fds[1];
- int ret;
-
- fd = pkt_nm->desc->fd;
- fds[0].fd = fd;
- fds[0].events = POLLIN;
-
- while (nb_rx < len) {
- ret = poll(fds, 1, POLL_TMO);
- if (ret <= 0 || (fds[0].revents & POLLERR))
- break;
-
- /* Find first ring not empty */
- while (nm_ring_empty(rxring)) {
- ringid++;
+ struct dispatch_args *args = (struct dispatch_args *)arg;
+ odp_packet_t pkt;
+ uint8_t *pkt_buf, *l2_hdr;
+ size_t frame_len;
- /* Return to scheduler if no more data to meet the
- requested amount (len) */
- if (ringid == pkt_nm->end) {
- ODP_DBG("No more data on the wire\n");
- break;
- }
+ frame_len = (size_t)hdr->len;
- rxring = NETMAP_RXRING(pkt_nm->desc->nifp, ringid);
- }
+ if (frame_len > args->pkt_nm->max_frame_len) {
+ ODP_ERR("[%04d] RX: frame too big %u %lu!\n",
+ odp_thread_id(),
+ (unsigned)frame_len, args->pkt_nm->max_frame_len);
+ return;
+ }
- if (ringid == pkt_nm->end)
- break;
+ if (odp_unlikely(frame_len < ODPH_ETH_LEN_MIN)) {
+ ODP_ERR("[%04d] RX: Frame truncated: %u\n",
+ odp_thread_id(),
+ (unsigned)frame_len);
+ return;
+ }
- limit = len - nb_rx;
- if (nm_ring_space(rxring) < limit)
- limit = nm_ring_space(rxring);
-
- for (rx = 0; rx < limit; rx++) {
- struct netmap_slot *rslot;
- char *p;
- uint16_t frame_len;
- uint8_t *pkt_buf;
- uint8_t *l2_hdr;
- uint32_t cur;
-
- if (odp_likely(pkt == ODP_PACKET_INVALID)) {
- pkt = odph_packet_alloc(pkt_nm->pool);
- if (odp_unlikely(pkt == ODP_PACKET_INVALID))
- break;
- }
-
- cur = rxring->cur;
- rslot = &rxring->slot[cur];
- p = NETMAP_BUF(rxring, rslot->buf_idx);
- frame_len = rslot->len;
-
- rxring->head = nm_ring_next(rxring, cur);
- rxring->cur = rxring->head;
-
- pkt_buf = odp_packet_addr(pkt);
- l2_hdr = pkt_buf + pkt_nm->frame_offset;
-
- if (frame_len > pkt_nm->max_frame_len) {
- ODP_ERR("RX: frame too big %u %lu!\n",
- frame_len, pkt_nm->max_frame_len);
- /* drop the frame, reuse pkt next interation */
- continue;
- }
- if (odp_unlikely(frame_len < ODPH_ETH_LEN_MIN)) {
- ODP_ERR("RX: Frame truncated: %u\n",
- (unsigned)frame_len);
- continue;
- }
-
- /* For now copy the data in the mbuf,
- worry about zero-copy later */
- memcpy(l2_hdr, p, frame_len);
-
- /* Initialize, parse and set packet header data */
- odp_packet_init(pkt);
- odp_packet_parse(pkt, frame_len, pkt_nm->frame_offset);
-
- pkt_table[nb_rx] = pkt;
- pkt = ODP_PACKET_INVALID;
- nb_rx++;
- }
+ pkt = odph_packet_alloc(args->pkt_nm->pool);
- if (odp_unlikely(pkt == ODP_PACKET_INVALID))
- break;
+ if (odp_unlikely(pkt == ODP_PACKET_INVALID)) {
+ ODP_DBG("[%04d] Could not allocate packet\n", odp_thread_id());
+ return;
}
+ pkt_buf = odp_packet_addr(pkt);
+ l2_hdr = pkt_buf + args->pkt_nm->frame_offset;
+ /* For now copy the data in the mbuf,
+ worry about zero-copy later */
+ memcpy(l2_hdr, buf, frame_len);
- if (odp_unlikely(pkt != ODP_PACKET_INVALID))
- odp_buffer_free((odp_buffer_t) pkt);
+ /* Initialize, parse and set packet header data */
+ odp_packet_init(pkt);
+ odp_packet_parse(pkt, frame_len, args->pkt_nm->frame_offset);
- return nb_rx;
+ args->pkt_table[args->nb_rx++] = pkt;
}
-int send_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
+int recv_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
unsigned len)
{
- struct netmap_ring *txring = pkt_nm->txring;
- int fd;
- unsigned nb_tx = 0;
- uint32_t limit, tx;
- uint32_t ringid = pkt_nm->begin;
- odp_packet_t pkt;
+ int fd = pkt_nm->desc->fd;
struct pollfd fds[1];
int ret;
+ struct dispatch_args args;
- fd = pkt_nm->desc->fd;
fds[0].fd = fd;
- fds[0].events = POLLOUT;
+ fds[0].events = POLLIN;
- while (nb_tx < len) {
- ret = poll(fds, 1, POLL_TMO);
- if (ret <= 0 || (fds[0].revents & POLLERR))
- break;
+ ret = poll(fds, 1, POLL_TMO);
+ if (ret <= 0 || (fds[0].revents & POLLERR))
+ return 0;
- /* Find first ring not empty */
- while (nm_ring_empty(txring)) {
- ringid++;
+ args.pkt_table = pkt_table;
+ args.nb_rx = 0;
+ args.pkt_nm = pkt_nm;
+ nm_dispatch(pkt_nm->desc, len, nm_recv_cb, (uint8_t *)&args);
- /* Return to scheduler if no more space to meet the
- requested amount (len) */
- if (ringid == pkt_nm->end) {
- ODP_DBG("No more space in TX rings\n");
- break;
- }
+ return args.nb_rx;
+}
- txring = NETMAP_TXRING(pkt_nm->desc->nifp, ringid);
- }
+int send_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
+ unsigned len)
+{
+ int fd = pkt_nm->desc->fd;
+ unsigned tx, nb_tx;
+ struct pollfd fds[2];
+ int ret;
- if (ringid == pkt_nm->end)
- break;
+ fds[0].fd = fd;
+ fds[0].events = POLLOUT;
- limit = len - nb_tx;
- if (nm_ring_space(txring) < limit)
- limit = nm_ring_space(txring);
-
- for (tx = 0; tx < limit; tx++) {
- struct netmap_slot *tslot;
- size_t frame_len;
- uint32_t cur;
- uint8_t *frame;
- void *txbuf;
-
- cur = txring->cur;
- tslot = &txring->slot[cur];
- txbuf = NETMAP_BUF(txring, tslot->buf_idx);
-
- pkt = pkt_table[nb_tx];
- frame = odp_packet_l2(pkt);
- frame_len = odp_packet_get_len(pkt);
-
- memcpy(txbuf, frame, frame_len);
- tslot->len = frame_len;
- txring->head = nm_ring_next(txring, cur);
- txring->cur = txring->head;
- nb_tx++;
- }
+ ret = poll(fds, 1, POLL_TMO);
+ if (ret <= 0 || (fds[0].revents & POLLERR))
+ goto out;
+
+ for (nb_tx = 0; nb_tx < len; nb_tx++) {
+ odp_packet_t pkt = pkt_table[nb_tx];
+ uint8_t *frame = odp_packet_l2(pkt);
+ size_t frame_len = odp_packet_get_len(pkt);
+ if (nm_inject(pkt_nm->desc, frame, frame_len) == 0)
+ break;
}
+out:
for (tx = 0; tx < len; tx++)
odph_packet_free(pkt_table[tx]);
Signed-off-by: Ciprian Barbu <ciprian.barbu@linaro.org> --- platform/linux-netmap/include/odp_packet_netmap.h | 4 - platform/linux-netmap/odp_packet_netmap.c | 218 +++++++--------------- 2 files changed, 71 insertions(+), 151 deletions(-)