Problem description
In VMWARE virtual machine, 82545EM virtual network card is bound with IGB_ After UIO, run the dpdk program, which always has the following alarm information:
Eal:Error reading from file descriptor 33: Input/output error
The dpdk version used is 16.04 and the program is l2fwd.
problem analysis
1. dpdk internal code
Code related to error reporting:
bytes_read = read(events[n].data.fd, &buf, bytes_read); if (bytes_read < 0) { if (errno == EINTR || errno == EWOULDBLOCK) continue; RTE_LOG(ERR, EAL, "Error reading from file " "descriptor %d: %s\n", events[n].data.fd, strerror(errno));
The result printed by strerror is Input/output error. Query the standard error value table. The relevant return values are defined as follows:
#define EIO 5 /* I/O error */
Indicates that the problem is that the EIO error value is returned when reading from the uio file. Then the problem comes. Where does the EIO return value come from?
2. Code in UIO module
The code of read callback function for uio file registration in uio module is as follows:
static ssize_t uio_read(struct file *filep, char __user *buf, size_t count, loff_t *ppos) { struct uio_listener *listener = filep->private_data; struct uio_device *idev = listener->dev; DECLARE_WAITQUEUE(wait, current); ssize_t retval; s32 event_count; if (!idev->info->irq) return -EIO;
UIO in the above code_ Read is the function finally called in the kernel when reading the / dev/uioX file. As can be seen from the above function logic, when the value of Idev - > Info - > IRQ is 0, an - EIO error will be returned.
So where is Idev - > Info - > IRQ initialized?
The study determined that it was in IGB_ Is initialized in UIO. C.
3. igb_ Initialize UIO in UIO. C_ Position of irq field in info structure
Relevant codes are as follows:
switch (igbuio_intr_mode_preferred) { case RTE_INTR_MODE_MSIX: /* Only 1 msi-x vector needed */ msix_entry.entry = 0; if (pci_enable_msix(dev, &msix_entry, 1) == 0) { dev_dbg(&dev->dev, "using MSI-X"); udev->info.irq = msix_entry.vector; udev->mode = RTE_INTR_MODE_MSIX; break; } /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(dev)) { dev_dbg(&dev->dev, "using INTX"); udev->info.irq_flags = IRQF_SHARED; udev->info.irq = dev->irq; udev->mode = RTE_INTR_MODE_LEGACY; break; } dev_notice(&dev->dev, "PCI INTX mask not supported\n"); /* fall back to no IRQ */ case RTE_INTR_MODE_NONE: udev->mode = RTE_INTR_MODE_NONE; udev->info.irq = 0; break; default: dev_err(&dev->dev, "invalid IRQ mode %u", igbuio_intr_mode_preferred); err = -EINVAL; goto fail_release_iomem; }
The above process is based on IGB_ Match the interrupt mode set when uio module is loaded. The default value is RTE_INTR_MODE_MSIX. In VMWARE environment, the 82545EM network card does not support msic and intx interrupt, and the process is executed to RTE_ INTR_ MODE_ In none case, the value of irq is set to 0, which causes dpdk to always report errors when reading uio files through read.
resolvent
Although the 82545EM virtual network card in VMWARE environment does not support msix and intx interrupts, the dpdk program can still run normally, which indicates that the interrupt function is not used to a certain extent.
At the same time, we analyzed the code and determined that only lsc interrupt was related, and we did not enable lsc interrupt for 82545EM network card.
Based on this fact, the IGB is modified_ UIO code. If it is determined that the network card model is 82545EM, execute RTE_ INTR_ MODE_ Process in legacy.
The test confirmed that the modified problem was solved.
Another optional modification scheme is not to register and listen for uio interrupt events for 82545EM network card in dpdk pmd driver.
The specific modification methods are as follows:
In eth_em_dev_init determines the network card model. If it is 82545EM, the interface PCI_ Intr in dev_ The fd field of handle is set to - 1.