struct pkt_tx_queue {
int sockfd;
+ unsigned int frame_data_size;
struct iovec *rd;
uint8_t *map;
unsigned nb_queues;
int if_index;
+ char *if_name;
struct ether_addr eth_addr;
struct tpacket_req req;
NULL
};
-static const char *drivername = "AF_PACKET PMD";
-
static struct rte_eth_link pmd_link = {
.link_speed = ETH_SPEED_NUM_10G,
.link_duplex = ETH_LINK_FULL_DUPLEX,
framenum = pkt_q->framenum;
ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base;
for (i = 0; i < nb_pkts; i++) {
+ mbuf = *bufs++;
+
+ /* drop oversized packets */
+ if (rte_pktmbuf_data_len(mbuf) > pkt_q->frame_data_size) {
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
+
/* point at the next incoming frame */
if ((ppd->tp_status != TP_STATUS_AVAILABLE) &&
(poll(&pfd, 1, -1) < 0))
- continue;
+ break;
/* copy the tx frame data */
- mbuf = bufs[num_tx];
pbuf = (uint8_t *) ppd + TPACKET2_HDRLEN -
sizeof(struct sockaddr_ll);
memcpy(pbuf, rte_pktmbuf_mtod(mbuf, void*), rte_pktmbuf_data_len(mbuf));
/* kick-off transmits */
if (sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1)
- return 0; /* error sending -- no packets transmitted */
+ num_tx = 0; /* error sending -- no packets transmitted */
pkt_q->framenum = framenum;
pkt_q->tx_pkts += num_tx;
- pkt_q->err_pkts += nb_pkts - num_tx;
+ pkt_q->err_pkts += i - num_tx;
pkt_q->tx_bytes += num_tx_bytes;
- return num_tx;
+ return i;
}
static int
sockfd = internals->rx_queue[i].sockfd;
if (sockfd != -1)
close(sockfd);
- sockfd = internals->tx_queue[i].sockfd;
- if (sockfd != -1)
- close(sockfd);
+
+ /* Prevent use after free in case tx fd == rx fd */
+ if (sockfd != internals->tx_queue[i].sockfd) {
+ sockfd = internals->tx_queue[i].sockfd;
+ if (sockfd != -1)
+ close(sockfd);
+ }
+
+ internals->rx_queue[i].sockfd = -1;
+ internals->tx_queue[i].sockfd = -1;
}
dev->data->dev_link.link_status = ETH_LINK_DOWN;
{
struct pmd_internals *internals = dev->data->dev_private;
- dev_info->driver_name = drivername;
dev_info->if_index = internals->if_index;
dev_info->max_mac_addrs = 1;
dev_info->max_rx_pktlen = (uint32_t)ETH_FRAME_LEN;
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->pci_dev = NULL;
}
static void
{
struct pmd_internals *internals = dev->data->dev_private;
struct pkt_rx_queue *pkt_q = &internals->rx_queue[rx_queue_id];
- uint16_t buf_size;
+ unsigned int buf_size, data_size;
pkt_q->mb_pool = mb_pool;
/* Now get the space available for data in the mbuf */
- buf_size = (uint16_t)(rte_pktmbuf_data_room_size(pkt_q->mb_pool) -
- RTE_PKTMBUF_HEADROOM);
+ buf_size = rte_pktmbuf_data_room_size(pkt_q->mb_pool) -
+ RTE_PKTMBUF_HEADROOM;
+ data_size = internals->req.tp_frame_size;
+ data_size -= TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);
- if (ETH_FRAME_LEN > buf_size) {
+ if (data_size > buf_size) {
RTE_LOG(ERR, PMD,
"%s: %d bytes will not fit in mbuf (%d bytes)\n",
- dev->data->name, ETH_FRAME_LEN, buf_size);
+ dev->data->name, data_size, buf_size);
return -ENOMEM;
}
return 0;
}
+static int
+eth_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct pmd_internals *internals = dev->data->dev_private;
+ struct ifreq ifr = { .ifr_mtu = mtu };
+ int ret;
+ int s;
+ unsigned int data_size = internals->req.tp_frame_size -
+ TPACKET2_HDRLEN -
+ sizeof(struct sockaddr_ll);
+
+ if (mtu > data_size)
+ return -EINVAL;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return -EINVAL;
+
+ strncpy(ifr.ifr_name, internals->if_name, IFNAMSIZ);
+ ret = ioctl(s, SIOCSIFMTU, &ifr);
+ close(s);
+
+ if (ret < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void
+eth_dev_change_flags(char *if_name, uint32_t flags, uint32_t mask)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return;
+
+ strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+ goto out;
+ ifr.ifr_flags &= mask;
+ ifr.ifr_flags |= flags;
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+ goto out;
+out:
+ close(s);
+}
+
+static void
+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);
+}
+
+static void
+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);
+}
+
static const struct eth_dev_ops ops = {
.dev_start = eth_dev_start,
.dev_stop = eth_dev_stop,
.dev_close = eth_dev_close,
.dev_configure = eth_dev_configure,
.dev_infos_get = eth_dev_info,
+ .mtu_set = eth_dev_mtu_set,
+ .promiscuous_enable = eth_dev_promiscuous_enable,
+ .promiscuous_disable = eth_dev_promiscuous_disable,
.rx_queue_setup = eth_rx_queue_setup,
.tx_queue_setup = eth_tx_queue_setup,
.rx_queue_release = eth_queue_release,
return 0;
}
+static struct rte_vdev_driver pmd_af_packet_drv;
+
static int
rte_pmd_init_internals(const char *name,
const int sockfd,
name);
goto error_early;
}
+ (*internals)->if_name = strdup(pair->value);
(*internals)->if_index = ifr.ifr_ifindex;
if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) {
tx_queue = &((*internals)->tx_queue[q]);
tx_queue->framecount = req->tp_frame_nr;
+ tx_queue->frame_data_size = req->tp_frame_size;
+ tx_queue->frame_data_size -= TPACKET2_HDRLEN -
+ sizeof(struct sockaddr_ll);
tx_queue->map = rx_queue->map + req->tp_block_size * req->tp_block_nr;
(*eth_dev)->dev_ops = &ops;
(*eth_dev)->driver = NULL;
(*eth_dev)->data->dev_flags = RTE_ETH_DEV_DETACHABLE;
- (*eth_dev)->data->drv_name = drivername;
+ (*eth_dev)->data->drv_name = pmd_af_packet_drv.driver.name;
(*eth_dev)->data->kdrv = RTE_KDRV_NONE;
(*eth_dev)->data->numa_node = numa_node;
((*internals)->rx_queue[q].sockfd != qsockfd))
close((*internals)->rx_queue[q].sockfd);
}
+ free((*internals)->if_name);
rte_free(*internals);
error_early:
rte_free(data);
rte_free(internals->rx_queue[q].rd);
rte_free(internals->tx_queue[q].rd);
}
+ free(internals->if_name);
rte_free(eth_dev->data->dev_private);
rte_free(eth_dev->data);
};
RTE_PMD_REGISTER_VDEV(net_af_packet, pmd_af_packet_drv);
+RTE_PMD_REGISTER_ALIAS(net_af_packet, eth_af_packet);
RTE_PMD_REGISTER_PARAM_STRING(net_af_packet,
"iface=<string> "
"qpairs=<int> "