@@ -26,17 +26,15 @@
/** Packet socket using netmap mmaped rings for both Rx and Tx */
typedef struct {
odp_buffer_pool_t pool;
- size_t max_frame_len; /**< max frame len = buf_size - sizeof(pkt_hdr) */
- size_t frame_offset; /**< frame start offset from start of pkt buf */
- size_t buf_size; /**< size of buffer payload in 'pool' */
- struct nm_desc *nm_desc;
- uint32_t begin;
- uint32_t end;
- struct netmap_ring *rxring;
- struct netmap_ring *txring;
- odp_queue_t tx_access; /* Used for exclusive access to send packets */
+ size_t max_frame_len; /**< buf_size - sizeof(pkt_hdr) */
+ size_t frame_offset; /**< Frame start 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 */
+ odp_queue_t tx_access; /**< Exclusive access to send packets */
uint32_t if_flags;
- char ifname[32];
+ odp_packet_t *pkt_table; /**< Used by recv_pkt_netmap */
+ int nb_rx; /**< Used by recv_pkt_netmap */
+ char ifname[IFNAMSIZ];
} pkt_netmap_t;
/**
@@ -103,7 +103,9 @@ static int nm_do_ioctl(pkt_netmap_t * const pkt_nm, unsigned long cmd,
case SIOCGIFFLAGS:
pkt_nm->if_flags = (ifr.ifr_flags << 16) |
(0xffff & ifr.ifr_flags);
- ODP_DBG("flags are 0x%x\n", pkt_nm->if_flags);
+ ODP_DBG("[%04d] flags are 0x%x\n",
+ odp_thread_id(),
+ pkt_nm->if_flags);
break;
default:
break;
@@ -119,7 +121,7 @@ done:
int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
odp_buffer_pool_t pool)
{
- char ifname[32];
+ char ifname[IFNAMSIZ];
odp_packet_t pkt;
uint8_t *pkt_buf;
uint8_t *l2_hdr;
@@ -144,7 +146,7 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
odph_packet_free(pkt);
- strncpy(pkt_nm->ifname, netdev, sizeof(pkt_nm->ifname));
+ snprintf(pkt_nm->ifname, sizeof(pkt_nm->ifname), "%s", netdev);
snprintf(ifname, sizeof(ifname), "netmap:%s", netdev);
odp_spinlock_lock(&mmap_desc_lock);
@@ -153,37 +155,34 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
mmap_desc.mem);
if (mmap_desc.mem == NULL)
- pkt_nm->nm_desc = nm_open(ifname, NULL, 0, NULL);
+ pkt_nm->desc = nm_open(ifname, NULL, 0, NULL);
else
- pkt_nm->nm_desc = nm_open(ifname, NULL, NM_OPEN_NO_MMAP,
+ pkt_nm->desc = nm_open(ifname, NULL, NM_OPEN_NO_MMAP,
&mmap_desc);
- if (pkt_nm->nm_desc == NULL) {
+ if (pkt_nm->desc == NULL) {
ODP_ERR("Error opening nm interface: %s\n", strerror(errno));
odp_spinlock_unlock(&mmap_desc_lock);
return -1;
}
if (mmap_desc.mem == NULL) {
- mmap_desc.mem = pkt_nm->nm_desc->mem;
- mmap_desc.memsize = pkt_nm->nm_desc->memsize;
+ mmap_desc.mem = pkt_nm->desc->mem;
+ mmap_desc.memsize = pkt_nm->desc->memsize;
}
odp_spinlock_unlock(&mmap_desc_lock);
- ODP_DBG("thread %d mmap addr %p\n",
+ ODP_DBG("[%04d] mmap addr %p\n",
odp_thread_id(),
- pkt_nm->nm_desc->mem);
-
- pkt_nm->begin = 0;
- pkt_nm->end = pkt_nm->nm_desc->req.nr_rx_rings;
- pkt_nm->rxring = NETMAP_RXRING(pkt_nm->nm_desc->nifp, 0);
- pkt_nm->txring = NETMAP_TXRING(pkt_nm->nm_desc->nifp, 0);
+ pkt_nm->desc->mem);
ret = nm_do_ioctl(pkt_nm, SIOCGIFFLAGS, 0);
if (ret)
return ret;
if ((pkt_nm->if_flags & IFF_UP) == 0) {
- ODP_DBG("%s is down, bringing up...\n", pkt_nm->ifname);
+ ODP_DBG("[%04d] %s is down, bringing up...\n",
+ odp_thread_id(),
+ pkt_nm->ifname);
pkt_nm->if_flags |= IFF_UP;
}
if (ETH_PROMISC) {
@@ -192,11 +191,13 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
}
ret = nm_do_ioctl(pkt_nm, SIOCETHTOOL, ETHTOOL_SGSO);
if (ret)
- ODP_DBG("ETHTOOL_SGSO not supported\n");
+ ODP_DBG("[%04d] ETHTOOL_SGSO not supported\n",
+ odp_thread_id());
ret = nm_do_ioctl(pkt_nm, SIOCETHTOOL, ETHTOOL_STSO);
if (ret)
- ODP_DBG("ETHTOOL_STSO not supported\n");
+ ODP_DBG("[%04d] ETHTOOL_STSO not supported\n",
+ odp_thread_id());
/* TODO: This seems to cause the app to not receive frames
* first time it is launched after netmap driver is inserted.
* Should be investigated further.
@@ -206,217 +207,132 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
*/
ret = nm_do_ioctl(pkt_nm, SIOCETHTOOL, ETHTOOL_STXCSUM);
if (ret)
- ODP_DBG("ETHTOOL_STXCSUM not supported\n");
+ ODP_DBG("[%04d] ETHTOOL_STXCSUM not supported\n",
+ odp_thread_id());
- ODP_DBG("Wait for link to come up\n");
+ ODP_DBG("[%04d] Wait for link to come up\n",
+ odp_thread_id());
sleep(WAITLINK_TMO);
- ODP_DBG("Done\n");
+ ODP_DBG("[%04d] Done\n",
+ odp_thread_id());
return 0;
}
int close_pkt_netmap(pkt_netmap_t * const pkt_nm)
{
- if (pkt_nm->nm_desc != NULL) {
- nm_close(pkt_nm->nm_desc);
- pkt_nm->nm_desc = NULL;
+ if (pkt_nm->desc != NULL) {
+ nm_close(pkt_nm->desc);
+ pkt_nm->desc = NULL;
}
return 0;
}
+static void nm_recv_cb(uint8_t *arg, const struct nm_pkthdr *hdr,
+ const uint8_t *buf)
+{
+ pkt_netmap_t *pkt_nm = (pkt_netmap_t *)arg;
+ odp_packet_t pkt;
+ uint8_t *pkt_buf, *l2_hdr;
+ size_t frame_len;
+
+ frame_len = (size_t)hdr->len;
+
+ if (frame_len > pkt_nm->max_frame_len) {
+ ODP_ERR("[%04d] RX: frame too big %u %lu!\n",
+ odp_thread_id(),
+ (unsigned)frame_len, pkt_nm->max_frame_len);
+ return;
+ }
+
+ if (odp_unlikely(frame_len < ODPH_ETH_LEN_MIN)) {
+ ODP_ERR("[%04d] RX: Frame truncated: %u\n",
+ odp_thread_id(),
+ (unsigned)frame_len);
+ return;
+ }
+
+ pkt = odph_packet_alloc(pkt_nm->pool);
+
+ 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 + pkt_nm->frame_offset;
+ /* For now copy the data in the mbuf,
+ worry about zero-copy later */
+ memcpy(l2_hdr, buf, frame_len);
+
+ /* Initialize, parse and set packet header data */
+ odp_packet_init(pkt);
+ odp_packet_parse(pkt, frame_len, pkt_nm->frame_offset);
+
+ pkt_nm->pkt_table[pkt_nm->nb_rx++] = pkt;
+}
+
int recv_pkt_netmap(pkt_netmap_t * const pkt_nm, odp_packet_t pkt_table[],
unsigned len)
{
- 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;
+ int fd = pkt_nm->desc->fd;
+
#ifdef NETMAP_BLOCKING_IO
struct pollfd fds[1];
int ret;
-#endif
- fd = pkt_nm->nm_desc->fd;
-#ifdef NETMAP_BLOCKING_IO
fds[0].fd = fd;
fds[0].events = POLLIN;
-#endif
- while (nb_rx < len) {
-#ifdef NETMAP_BLOCKING_IO
- ret = poll(&fds[0], 1, POLL_TMO);
- if (ret <= 0 || (fds[0].revents & POLLERR))
- break;
+ ret = poll(&fds[0], 1, POLL_TMO);
+ if (ret <= 0 || (fds[0].revents & POLLERR))
+ return 0;
#else
- ioctl(fd, NIOCRXSYNC, NULL);
+ ioctl(fd, NIOCRXSYNC, NULL);
#endif
- /* Find first ring not empty */
- while (nm_ring_empty(rxring)) {
- ringid++;
-
- /* 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;
- }
-
- rxring = NETMAP_RXRING(pkt_nm->nm_desc->nifp, ringid);
- }
-
- limit = len - nb_rx;
- if (nm_ring_space(rxring) < limit)
- limit = nm_ring_space(rxring);
-
- ODP_DBG("receiving %d frames out of %u\n", limit, len);
-
- 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++;
- }
-
- if (odp_unlikely(pkt == ODP_PACKET_INVALID))
- break;
- }
+ pkt_nm->pkt_table = pkt_table;
+ pkt_nm->nb_rx = 0;
+ nm_dispatch(pkt_nm->desc, len, nm_recv_cb, (uint8_t *)pkt_nm);
- if (odp_unlikely(pkt != ODP_PACKET_INVALID))
- odp_buffer_free((odp_buffer_t) pkt);
+ if (pkt_nm->nb_rx)
+ ODP_DBG("[%04d] <=== rcvd %03u frames from netmap adapter\n",
+ odp_thread_id(), pkt_nm->nb_rx);
- if (nb_rx)
- ODP_DBG("<=== rcvd %03u frames from netmap adapter\n", nb_rx);
-
- return nb_rx;
+ return pkt_nm->nb_rx;
}
int send_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;
+ unsigned tx, nb_tx;
#ifdef NETMAP_BLOCKING_IO
struct pollfd fds[2];
int ret;
-#endif
- fd = pkt_nm->nm_desc->fd;
-#ifdef NETMAP_BLOCKING_IO
fds[0].fd = fd;
fds[0].events = POLLOUT;
-#endif
- while (nb_tx < len) {
-#ifdef NETMAP_BLOCKING_IO
- ret = poll(&fds[0], 1, POLL_TMO);
- if (ret <= 0 || (fds[0].revents & POLLERR))
- break;
+ ret = poll(&fds[0], 1, POLL_TMO);
+ if (ret <= 0 || (fds[0].revents & POLLERR))
+ return 0;
#else
- ioctl(fd, NIOCTXSYNC, NULL);
+ ioctl(fd, NIOCTXSYNC, NULL);
#endif
- /* Find first ring not empty */
- while (nm_ring_empty(txring)) {
- ringid++;
-
- /* 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;
- }
-
- txring = NETMAP_TXRING(pkt_nm->nm_desc->nifp, ringid);
- }
-
- limit = len - nb_tx;
- if (nm_ring_space(txring) < limit)
- limit = nm_ring_space(txring);
-
- ODP_DBG("Sending %d packets out of %d to netmap %p %u\n",
- limit, len, txring, txring->cur);
-
- 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++;
- }
+ 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))
+ break;
}
-#ifndef NETMAP_BLOCKING_IO
- ioctl(fd, NIOCTXSYNC, NULL);
-#endif
-
if (nb_tx)
- ODP_DBG("===> sent %03u frames to netmap adapter\n", nb_tx);
+ ODP_DBG("[%04d] ===> sent %03u frames to netmap adapter\n",
+ odp_thread_id(), nb_tx);
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 | 18 +- platform/linux-netmap/odp_packet_netmap.c | 280 ++++++++-------------- 2 files changed, 106 insertions(+), 192 deletions(-)