dpdk +vfio 中断关和开

本文探讨了DPDK结合VFIO在Linux环境下进行中断管理的方法。在普通网卡驱动中,中断通过写寄存器来开启和关闭。而在DPDK初始化过程中,中断配置涉及不同的寄存器操作。文章详细介绍了DPDK如何进行中断的启用和禁用,同时引用了相关资料以供深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、request_irq会去写mxi msg

普通网卡驱动申请中断

int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
{
​
    err = ixgbe_alloc_q_vectors(adapter);
​
}
static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
{
​
    if (q_vectors >= (rxr_remaining + txr_remaining)) {
        for (; rxr_remaining; v_idx++) {
            err = ixgbe_alloc_q_vector(adapter, q_vectors, v_idx,
                           0, 0, 1, rxr_idx);
​
            if (err)
                goto err_out;
​
            /* update counts and index */
            rxr_remaining--;
            rxr_idx++;
        }
    }
}
static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
                int v_count, int v_idx,
                int txr_count, int txr_idx,
                int rxr_count, int rxr_idx)
{
    /* setup affinity mask and node */
    if (cpu != -1)
        cpumask_set_cpu(cpu, &q_vector->affinity_mask);
    q_vector->numa_node = node;
​
#ifdef CONFIG_IXGBE_DCA
    /* initialize CPU for DCA */
    q_vector->cpu = -1;
​
#endif
    /* initialize NAPI */
    netif_napi_add(adapter->netdev, &q_vector->napi,
               ixgbe_poll, 64);
    napi_hash_add(&q_vector->napi);
}
static int ixgbe_open(struct net_device *netdev)
{
    /* allocate transmit descriptors */
    err = ixgbe_setup_all_tx_resources(adapter);
    if (err)
        goto err_setup_tx;
​
    /* allocate receive descriptors */
    err = ixgbe_setup_all_rx_resources(adapter);
    /*注册中断*/
    err = ixgbe_request_irq(adapter);
}
​
static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
{
    struct net_device *netdev = adapter->netdev;
    int err;
​
    if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
        err = ixgbe_request_msix_irqs(adapter);
    else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED)
        err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
                  netdev->name, adapter);
    else
        err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
                  netdev->name, adapter);
​
    if (err)
        e_err(probe, "request_irq failed, Error %d\n", err);
​
    return err;
}
​
static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
{
    for (vector = 0; vector < adapter->num_q_vectors; vector++) {
        struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
        struct msix_entry *entry = &adapter->msix_entries[vector];
​
        err = request_irq(entry->vector, &ixgbe_msix_clean_rings, 0,
                  q_vector->name, q_vector);
    }
}

开中断

int igb_up(struct igb_adapter *adapter)
{
    struct e1000_hw *hw = &adapter->hw;
    int i;
​
    /* hardware has been reset, we need to reload some things */
    igb_configure(adapter);
​
    clear_bit(__IGB_DOWN, &adapter->state);
​
    for (i = 0; i < adapter->num_q_vectors; i++)
        napi_enable(&(adapter->q_vector[i]->napi));
​
    if (adapter->msix_entries)
        igb_configure_msix(adapter);
    else
        igb_assign_vector(adapter->q_vector[0], 0);
​
    /* Clear any pending interrupts. */
    rd32(E1000_ICR);
    igb_irq_enable(adapter);
​
    /* notify VFs that reset has been completed */
    if (adapter->vfs_allocated_count) {
        u32 reg_data = rd32(E1000_CTRL_EXT);
        reg_data |= E1000_CTRL_EXT_PFRSTD;
        wr32(E1000_CTRL_EXT, reg_data);
    }
​
    netif_tx_start_all_queues(adapter->netdev);
​
    /* start the watchdog. */
    hw->mac.get_link_status = 1;
    schedule_work(&adapter->watchdog_task);
​
    return 0;
}
 **/
static void igb_irq_enable(struct igb_adapter *adapter)
{
    struct e1000_hw *hw = &adapter->hw;
​
    if (adapter->msix_entries) {
        u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_DRSTA;
        u32 regval = rd32(E1000_EIAC);
        wr32(E1000_EIAC, regval | adapter->eims_enable_mask);
        regval = rd32(E1000_EIAM);
        wr32(E1000_EIAM, regval | adapter->eims_enable_mask);
        wr32(E1000_EIMS, adapter->eims_enable_mask);
        if (adapter->vfs_allocated_count) {
            wr32(E1000_MBVFIMR, 0xFF);
            ims |= E1000_IMS_VMMB;
        }
        wr32(E1000_IMS, ims);
    } else {
        wr32(E1000_IMS, IMS_ENABLE_MASK |
                E1000_IMS_DRSTA);
        wr32(E1000_IAM, IMS_ENABLE_MASK |
                E1000_IMS_DRSTA);
    }
}

到这里,几乎所有的准备工作都就绪了。唯一剩下的就是打开硬中断,等待数据包进来。打开硬中断的方

DPDK中,UIO(User-space I/O)VFIO(Virtual Function I/O)驱动扮演着至重要的角色,它们是实现高性能网络数据包处理的键技术组件。首先,让我们先了解这两个驱动的工作原理: 参考资源链接:[DPDK开发全攻略:从入门到精通](https://wenku.youkuaiyun.com/doc/5wtby67bam?spm=1055.2569.3001.10343) 1. UIO驱动:UIO是一种Linux内核机制,允许用户空间程序直接访问硬件设备。它通过将设备的内存映射到用户空间,让应用程序能够绕过内核,直接与设备通信。在DPDK中,UIO驱动用于将网络接口控制器(NIC)映射到用户空间,从而减少由内核管理的中断带来的延迟。具体操作包括加载UIO内核模块,比如uio_pSeries或igb_uio,然后将NIC绑定到相应的UIO驱动,之后应用程序就可以直接操作NIC设备的内存寄存器。 2. VFIO驱动:VFIO提供了一种更加先进的方式来实现硬件设备的用户空间访问。与UIO相比,VFIO提供了更多的功能,比如对设备的IOMMU保护、直接设备赋值(DDI)以及设备虚拟化。在DPDK中使用VFIO时,通常会涉及到Intel VT-d技术,这允许用户空间程序直接访问物理设备,从而实现更高的I/O性能。通过VFIODPDK可以实现更好的隔离安全性,同时提升数据包处理的速度。 在DPDK中,通过配置相应的UIO或VFIO驱动,应用程序可以实现对NIC的高效控制。应用程序可以使用DPDK提供的内存池、轮询模式驱动(PMD)、无锁队列等API来构建高性能的数据包处理管道。这些API允许应用程序实现零拷贝、零复制的数据传输,显著提升了处理大量数据包时的吞吐量效率。 举例来说,当一个数据包到达NIC时,通过UIO或VFIO,应用程序可以直接从NIC的接收队列中读取数据包,而无需内核介入。这一过程大大减少了延迟,并允许应用程序以极高的速率处理数据包。此外,DPDK还提供了自动的中断模式,可以闭或减少中断频率,进一步优化了性能。 为了更好地理解运用DPDK中的UIOVFIO驱动,推荐查阅《DPDK开发全攻略:从入门到精通》。这本书详细讲解了DPDK的使用方法,包括如何配置UIOVFIO驱动,并且包含了大量实例最佳实践,非常适合初学者希望进一步深入学习的开发者。通过这本书,你可以更全面地掌握DPDK开发键技术,并解决实际开发中的常见问题。 参考资源链接:[DPDK开发全攻略:从入门到精通](https://wenku.youkuaiyun.com/doc/5wtby67bam?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值