#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <net/if.h>
+#include <net/if_arp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#define DFLT_FRAME_SIZE (1 << 11)
#define DFLT_FRAME_COUNT (1 << 9)
-#define RTE_PMD_AF_PACKET_MAX_RINGS 16
-
struct pkt_rx_queue {
int sockfd;
struct tpacket_req req;
- struct pkt_rx_queue rx_queue[RTE_PMD_AF_PACKET_MAX_RINGS];
- struct pkt_tx_queue tx_queue[RTE_PMD_AF_PACKET_MAX_RINGS];
+ struct pkt_rx_queue *rx_queue;
+ struct pkt_tx_queue *tx_queue;
};
static const char *valid_arguments[] = {
}
/* kick-off transmits */
- if (sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1) {
- /* error sending -- no packets transmitted */
+ if (sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1 &&
+ errno != ENOBUFS && errno != EAGAIN) {
+ /*
+ * In case of a ENOBUFS/EAGAIN error all of the enqueued
+ * packets will be considered successful even though only some
+ * are sent.
+ */
+
num_tx = 0;
num_tx_bytes = 0;
}
dev_info->max_rx_queues = (uint16_t)internals->nb_queues;
dev_info->max_tx_queues = (uint16_t)internals->nb_queues;
dev_info->min_rx_bufsize = 0;
+ dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MULTI_SEGS |
+ DEV_TX_OFFLOAD_VLAN_INSERT;
return 0;
}
return 0;
}
-static void
+static int
eth_stats_reset(struct rte_eth_dev *dev)
{
unsigned i;
internal->tx_queue[i].err_pkts = 0;
internal->tx_queue[i].tx_bytes = 0;
}
+
+ return 0;
}
static void
return 0;
}
-static void
+static int
+eth_dev_macaddr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ struct ifreq ifr = { };
+ int sockfd = internals->rx_queue[0].sockfd;
+ int ret;
+
+ if (sockfd == -1) {
+ PMD_LOG(ERR, "receive socket not found");
+ return -EINVAL;
+ }
+
+ strlcpy(ifr.ifr_name, internals->if_name, IFNAMSIZ);
+ ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
+ memcpy(ifr.ifr_hwaddr.sa_data, addr, sizeof(*addr));
+ ret = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
+
+ if (ret < 0) {
+ PMD_LOG_ERRNO(ERR, "ioctl(SIOCSIFHWADDR) failed");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
eth_dev_change_flags(char *if_name, uint32_t flags, uint32_t mask)
{
struct ifreq ifr;
+ int ret = 0;
int s;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
- return;
+ return -errno;
strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+ ret = -errno;
goto out;
+ }
ifr.ifr_flags &= mask;
ifr.ifr_flags |= flags;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+ ret = -errno;
goto out;
+ }
out:
close(s);
+ return ret;
}
-static void
+static int
eth_dev_promiscuous_enable(struct rte_eth_dev *dev)
{
struct pmd_internals *internals = dev->data->dev_private;
- eth_dev_change_flags(internals->if_name, IFF_PROMISC, ~0);
+ return eth_dev_change_flags(internals->if_name, IFF_PROMISC, ~0);
}
-static void
+static int
eth_dev_promiscuous_disable(struct rte_eth_dev *dev)
{
struct pmd_internals *internals = dev->data->dev_private;
- eth_dev_change_flags(internals->if_name, 0, ~IFF_PROMISC);
+ return eth_dev_change_flags(internals->if_name, 0, ~IFF_PROMISC);
}
static const struct eth_dev_ops ops = {
.dev_close = eth_dev_close,
.dev_configure = eth_dev_configure,
.dev_infos_get = eth_dev_info,
+ .mac_addr_set = eth_dev_macaddr_set,
.mtu_set = eth_dev_mtu_set,
.promiscuous_enable = eth_dev_promiscuous_enable,
.promiscuous_disable = eth_dev_promiscuous_disable,
if (*internals == NULL)
return -1;
+
+ (*internals)->rx_queue = rte_calloc_socket("af_packet_rx",
+ nb_queues,
+ sizeof(struct pkt_rx_queue),
+ 0, numa_node);
+ (*internals)->tx_queue = rte_calloc_socket("af_packet_tx",
+ nb_queues,
+ sizeof(struct pkt_tx_queue),
+ 0, numa_node);
+ if (!(*internals)->rx_queue || !(*internals)->tx_queue) {
+ rte_free((*internals)->rx_queue);
+ rte_free((*internals)->tx_queue);
+ return -1;
+ }
+
for (q = 0; q < nb_queues; q++) {
(*internals)->rx_queue[q].map = MAP_FAILED;
(*internals)->tx_queue[q].map = MAP_FAILED;
pair = &kvlist->pairs[k_idx];
if (strstr(pair->key, ETH_AF_PACKET_NUM_Q_ARG) != NULL) {
qpairs = atoi(pair->value);
- if (qpairs < 1 ||
- qpairs > RTE_PMD_AF_PACKET_MAX_RINGS) {
+ if (qpairs < 1) {
PMD_LOG(ERR,
"%s: invalid qpairs value",
name);
rte_free(internals->tx_queue[q].rd);
}
free(internals->if_name);
+ rte_free(internals->rx_queue);
+ rte_free(internals->tx_queue);
rte_eth_dev_release_port(eth_dev);