#include <rte_string_fns.h>
#include <rte_mbuf.h>
-#include <rte_ethdev_driver.h>
-#include <rte_ethdev_vdev.h>
+#include <ethdev_driver.h>
+#include <ethdev_vdev.h>
#include <rte_malloc.h>
#include <rte_kvargs.h>
#include <rte_bus_vdev.h>
.link_autoneg = ETH_LINK_FIXED,
};
-RTE_LOG_REGISTER(af_packet_logtype, pmd.net.packet, NOTICE);
+RTE_LOG_REGISTER_DEFAULT(af_packet_logtype, NOTICE);
#define PMD_LOG(level, fmt, args...) \
rte_log(RTE_LOG_ ## level, af_packet_logtype, \
return num_rx;
}
+/*
+ * Check if there is an available frame in the ring
+ */
+static inline bool
+tx_ring_status_available(uint32_t tp_status)
+{
+ /*
+ * We eliminate the timestamp status from the packet status.
+ * This should only matter if timestamping is enabled on the socket,
+ * but there is a bug in the kernel which is fixed in newer releases.
+ *
+ * See the following kernel commit for reference:
+ * commit 171c3b151118a2fe0fc1e2a9d1b5a1570cfe82d2
+ * net: packetmmap: fix only tx timestamp on request
+ */
+ tp_status &= ~(TP_STATUS_TS_SOFTWARE | TP_STATUS_TS_RAW_HARDWARE);
+
+ return tp_status == TP_STATUS_AVAILABLE;
+}
+
/*
* Callback to handle sending packets through a real NIC.
*/
}
/* point at the next incoming frame */
- if ((ppd->tp_status != TP_STATUS_AVAILABLE) &&
- (poll(&pfd, 1, -1) < 0))
+ if (!tx_ring_status_available(ppd->tp_status) &&
+ poll(&pfd, 1, -1) < 0)
break;
/* copy the tx frame data */
/*
* This function gets called when the current port gets stopped.
*/
-static void
+static int
eth_dev_stop(struct rte_eth_dev *dev)
{
unsigned i;
}
dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ return 0;
}
static int
return 0;
}
-static void
-eth_dev_close(struct rte_eth_dev *dev __rte_unused)
+static int
+eth_dev_close(struct rte_eth_dev *dev)
{
+ struct pmd_internals *internals;
+ struct tpacket_req *req;
+ unsigned int q;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ PMD_LOG(INFO, "Closing AF_PACKET ethdev on NUMA socket %u",
+ rte_socket_id());
+
+ internals = dev->data->dev_private;
+ req = &internals->req;
+ for (q = 0; q < internals->nb_queues; q++) {
+ munmap(internals->rx_queue[q].map,
+ 2 * req->tp_block_size * req->tp_block_nr);
+ rte_free(internals->rx_queue[q].rd);
+ rte_free(internals->tx_queue[q].rd);
+ }
+ free(internals->if_name);
+ rte_free(internals->rx_queue);
+ rte_free(internals->tx_queue);
+
+ /* mac_addrs must not be freed alone because part of dev_private */
+ dev->data->mac_addrs = NULL;
+ return 0;
}
static void
goto error;
}
+ if (qdisc_bypass) {
#if defined(PACKET_QDISC_BYPASS)
- rc = setsockopt(qsockfd, SOL_PACKET, PACKET_QDISC_BYPASS,
- &qdisc_bypass, sizeof(qdisc_bypass));
- if (rc == -1) {
- PMD_LOG_ERRNO(ERR,
- "%s: could not set PACKET_QDISC_BYPASS on AF_PACKET socket for %s",
- name, pair->value);
- goto error;
- }
-#else
- RTE_SET_USED(qdisc_bypass);
+ rc = setsockopt(qsockfd, SOL_PACKET, PACKET_QDISC_BYPASS,
+ &qdisc_bypass, sizeof(qdisc_bypass));
+ if (rc == -1) {
+ PMD_LOG_ERRNO(ERR,
+ "%s: could not set PACKET_QDISC_BYPASS on AF_PACKET socket for %s",
+ name, pair->value);
+ goto error;
+ }
#endif
+ }
rc = setsockopt(qsockfd, SOL_PACKET, PACKET_RX_RING, req, sizeof(*req));
if (rc == -1) {
data->nb_tx_queues = (uint16_t)nb_queues;
data->dev_link = pmd_link;
data->mac_addrs = &(*internals)->eth_addr;
+ data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
(*eth_dev)->dev_ops = &ops;
if (qsockfd != -1)
close(qsockfd);
for (q = 0; q < nb_queues; q++) {
- munmap((*internals)->rx_queue[q].map,
- 2 * req->tp_block_size * req->tp_block_nr);
+ if ((*internals)->rx_queue[q].map != MAP_FAILED)
+ munmap((*internals)->rx_queue[q].map,
+ 2 * req->tp_block_size * req->tp_block_nr);
rte_free((*internals)->rx_queue[q].rd);
rte_free((*internals)->tx_queue[q].rd);
static int
rte_pmd_af_packet_remove(struct rte_vdev_device *dev)
{
- struct rte_eth_dev *eth_dev = NULL;
- struct pmd_internals *internals;
- struct tpacket_req *req;
- unsigned q;
-
- PMD_LOG(INFO, "Closing AF_PACKET ethdev on numa socket %u",
- rte_socket_id());
+ struct rte_eth_dev *eth_dev;
if (dev == NULL)
return -1;
/* find the ethdev entry */
eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
if (eth_dev == NULL)
- return -1;
-
- /* mac_addrs must not be freed alone because part of dev_private */
- eth_dev->data->mac_addrs = NULL;
-
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return rte_eth_dev_release_port(eth_dev);
-
- internals = eth_dev->data->dev_private;
- req = &internals->req;
- for (q = 0; q < internals->nb_queues; q++) {
- munmap(internals->rx_queue[q].map,
- 2 * req->tp_block_size * req->tp_block_nr);
- rte_free(internals->rx_queue[q].rd);
- rte_free(internals->tx_queue[q].rd);
- }
- free(internals->if_name);
- rte_free(internals->rx_queue);
- rte_free(internals->tx_queue);
+ return 0; /* port already released */
+ eth_dev_close(eth_dev);
rte_eth_dev_release_port(eth_dev);
return 0;