在drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 中会注册一个pci driver
static struct pci_driver ixgbe_driver = {
    .name     = ixgbe_driver_name,
    .id_table = ixgbe_pci_tbl,
    .probe    = ixgbe_probe,
    .remove   = ixgbe_remove,
#ifdef CONFIG_PM
    .suspend  = ixgbe_suspend,
    .resume   = ixgbe_resume,
#endif
    .shutdown = ixgbe_shutdown,
    .sriov_configure = ixgbe_pci_sriov_configure,
    .err_handler = &ixgbe_err_handler
};
 每个pcie设备都有一个pci_driver。其中提供了一个sriov_configure 用于开启vf。
int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
{
    if (num_vfs == 0)
        return ixgbe_pci_sriov_disable(dev);
    else
        return ixgbe_pci_sriov_enable(dev, num_vfs);
}
ixgbe_pci_sriov_configure 接受两个参数,一个是struct pci_dev *dev 代表这个pcie 设备,也就是pf,int num_vfs 也就是需要开启的vf的序列号,因为一个pf可以支持多个vf,所以要选择启动哪个vf.pf支持的vf个数是在sriov_init 中就已经初始化好的.
如果num_vfs 不是0的话,就调用ixgbe_pci_sriov_enable
static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
{
#ifdef CONFIG_PCI_IOV
    struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
    int err = 0;
    int i;
    int pre_existing_vfs = pci_num_vf(dev);
    err = pci_enable_sriov(dev, num_vfs);
    if (err) {
        e_dev_warn("Failed to enable PCI sriov: %d\n", err);
        return err;
    }
    return num_vfs;
#else
    return 0;
#endif
}
要使用vf,kernel必须打开CONFIG_PCI_IOV。随后调用pci_enable_sriov来启动vf
pci_enable_sriov->sriov_enable->pci_iov_add_virtfn
int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
{
    int i;
    int rc = -ENOMEM;
    u64 size;
    char buf[VIRTFN_ID_LEN];
    struct pci_dev *virtfn;
    struct resource *res;
    struct pci_sriov *iov = dev->sriov;
    struct pci_bus *bus;

mutex_lock(&iov->dev->sriov->lock);
//得到vf的bus
    bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id));
    if (!bus)
        goto failed;
//申请一个struct pci_dev *virtfn; 作为vf,在kernel中用pci_dev 表示一个pcie end point,从这里能看出vf和pf在kernel中的结构体是一样的
    virtfn = pci_alloc_dev(bus);
    if (!virtfn)
        goto failed0;

virtfn->devfn = pci_iov_virtfn_devfn(dev, id);
    virtfn->vendor = dev->vendor;
    pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
//初始化virtfn
    rc = pci_setup_device(virtfn);
    if (rc)
        goto failed0;

virtfn->dev.parent = dev->dev.parent;
    virtfn->physfn = pci_dev_get(dev);
    virtfn->is_virtfn = 1;
    virtfn->multifunction = 0;
//为vf准备bar资源,所以vf是有独立的bar资源的.
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
        res = &dev->resource[i + PCI_IOV_RESOURCES];
        if (!res->parent)
            continue;
        virtfn->resource[i].name = pci_name(virtfn);
        virtfn->resource[i].flags = res->flags;
        size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
        virtfn->resource[i].start = res->start + size * id;
        virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
        rc = request_resource(res, &virtfn->resource[i]);
        BUG_ON(rc);
    }

if (reset)
        __pci_reset_function(virtfn);
//添加device
    pci_device_add(virtfn, virtfn->bus);
    mutex_unlock(&iov->dev->sriov->lock);

pci_bus_add_device(virtfn);
    sprintf(buf, "virtfn%u", id);
//为vf建立sysfs接口
    rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
    if (rc)
        goto failed1;
    rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");
    if (rc)
        goto failed2;

kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);

return 0;

failed2:
    sysfs_remove_link(&dev->dev.kobj, buf);
failed1:
    pci_dev_put(dev);
    mutex_lock(&iov->dev->sriov->lock);
    pci_stop_and_remove_bus_device(virtfn);
failed0:
    virtfn_remove_bus(dev->bus, bus);
failed:
    mutex_unlock(&iov->dev->sriov->lock);

return rc;
}
 总结一下,要使用vf必须通过pf中的sriov_configure,在kernel中vf和pf都是用pci_dev,且初始化的flow也都是一样的,也就是说vf是一个独立的pcie 设备.且vf本身自己拥有资源.

ixgbe 如何开启vf相关推荐

  1. 使用Intel82599 VF 功能,在虚拟机里运行 (f-stack)nginx 代理功能多进程总结

    f-stack 官网F-Stack | High Performance Network Framework Based On DPDK f-stack是一个移植了freebsd 协议栈和支持dpdk ...

  2. linux加载虚拟sriov网卡,如何配置BroadCOM网卡的SR-IOV功能

    本案例中使用的服务器测试环境如下: 服务器:H3C R390X G2 操作系统:RHEL7.3 SR-IOV网卡型号:Brocadcom 530FLB (BCM57810芯片) 1.    首先在BI ...

  3. Mellanox CX-5网卡支持OVS流表加速功能的调研

    女主宣言 本文主要对Mellanox CX-5网卡支持OVS流表加速功能进行了调研,简单介绍了配套软件的版本要求,并描述了整体测试的步骤,另外对其支持VF热迁移也进行了初步的调研,希望对有相同需求的同 ...

  4. SR-IOV(Single Root I/O Virtualization):将PCIe共享给虚拟机的标准

    目录 SR-IOV要求 SR-IOV vs PCI path-through 架构上的比较(以网卡为例) Virtio 和 Pass-Through 的详细比较 SR-IOV vs DPDK SR-I ...

  5. 如何将SNS光纤交换机(OEM博科FC交换机)恢复为出厂设置

    解决方案 可以用命令configdefault恢复光纤交换机到出厂配置. configdefault命令有3个参数选项: -fid:交换机开启VF(virtual fabric)的时候,可以用逻辑交换 ...

  6. 深入理解SR-IOV和IO虚拟化

    一.背景 SR-IOV(Single Root I/O Virtualization)是由PCI-SIG组织定义的PCIe规范的扩展规范<Single Root I/O Virtualizati ...

  7. SR-IOV的简单理解

    SR-IOV的全程是single root I/O virtualization.物理的设备被叫做physical function(PV),一个PF 可以虚拟出virtual devices(VF) ...

  8. Translation Lookaside Buffer (TLB)

    CPU每次访问虚拟内存,虚拟地址都必须转换为对应的物理地址.从概念上说,这个转换需要遍历页表,页表是三级页表,就需要3次内存访问.就是说,每次虚拟内存访问都会导致4次物理内存访问.简单点说,如果一次虚 ...

  9. Mellanox CX6设置SR-IOV模式

    Mellanox CX6设置SR-IOV模式 1.背景 主机系统:rocky8.7 虚拟机系统:rocky8.7 网卡类型:Mellanox CX6-DX 2.主机环境配置 1)关闭防火墙.selin ...

最新文章

  1. ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route
  2. v-for遍历数组 || v-for遍历对象
  3. cath数据库fasta备注_数据库(同源)搜索软件 FASTA 和 BLAST
  4. Nginx的目录结构分析
  5. 为多孔介质的当量直径_多孔介质流建模简介
  6. Spring boot 项目目录结构详解
  7. Python 操作 Azure Blob Storage
  8. winform中listview选中整行_Excel办公实操,操作区域的3大小技巧,办公中的你使用过吗...
  9. Rust: 如何交换Vec类型中数据的位置?
  10. 税务计算机类考试题型,2020年税务师考试题型、计算器使用规定及考试难度
  11. MySql -- 数据库备份工具xtrabackup
  12. HTML表格——使用CSS冻结行和列
  13. 如何不靠运气变得富有 (十四) —— 特殊技能(specific knowledge)极富创造性或技术性
  14. 困扰我两天的问题(nginx配置好ssl证书,https却不能访问)
  15. SAP采购订单价格与信息记录价格不匹配
  16. spring入门学习粗解(一)
  17. Vue 中Lodop 实现批量打印
  18. 有哪些好用的思维导图软件?
  19. 基于红外热成像的行人检测方法
  20. 5G无用时代的终结—从iPhone 12系列到vivo 6G应用场景的展望

热门文章

  1. python股票数据简单分析
  2. nginx-----部署集群
  3. ***.jar!\BOOT-INF\classes!\***.xml没有此文件
  4. CodeForces 74 C.Chessboard Billiard(并查集)
  5. 高数 04.03分部积分法
  6. VB如何自动保存_VB开发的身份证个人信息自动识别软件
  7. 最大公约最小公倍数算法
  8. 逆向攻击破解安卓游戏
  9. 利用audacity分析浊音、清音、爆破音的时域及频域特性
  10. Swing设置窗体背景图片