I/O Operations and Activities
使用SR-IOV 的根本原因就是使得虚拟机中的一个驱动可以直接访问PCI进行I/O操作,并能够在虚拟机之间共享设备。Intel VF 驱动了解自己运行在一个虚拟化的环境中拥有优先的PCI资源。
可用的资源包括基本的接收和发送以太网包的能力,Intel VF 还提供了额外的硬件包括:
·状态信息:
·链路速度
·链路状态
·复用模式
·统计数据包括:
·收到的包计数
·发送的包计数
·收到的八位组计数
·发送的八位组计数
·收到的多播包计数
·功能级的复位(Function Level Reset)
·VLAN 标号插入
·校验和插入
Actions taken via Mailbox system - VF to PF
VF 暴露给VF驱动的PCI资源并不一定满足所有PF 驱动的需求,比如VLAN 标识配置和多播地址配置。
在这种情况下,VF驱动利用信箱 系统来向PF驱动传递消息,这样来使得PF驱动进行需要的操作。
现在定义的可以使用信箱机制实现的行为包括:
·VF复位
·配置VF MAC 地址
·设置多播地址
·设置VLAN过滤器
·设置最大包长
·信箱消息的ID实在ixgbe_mbx.h中定义的,适用于ixgbe PF 驱动和 ixgbevf VF 驱动
Virtual Function 复位:
消息ID:IXGBE_VF_RESET
驱动在执行了功能级的复位(Function Level Reset)后就会把这个消息发送给PF驱动。
一个例子:
文件:ixgbe_vf.c
函数:ixgbe_reset_hw_vf
msgbuf[0] = IXGBE_VF_RESET;
mbx->ops.write_posted(hw,msgbuf,1,0);
当PF驱动接收到消息,就会进行回复,并发送回MAC地址给VF。
Configuring a MAC Address
消息ID: IXGBE_VF_SET_MAC_ADDR
当VF驱动想要定义自己的MAC地址时,就会发送该消息(而不是使用当PF初始化时分配给VF的默认MAC地址)。
实例:
文件:ixgbex_vf.c
函数:ixgbe_set_rar_vf
msbuf[0] = IXGBE_VF_SET_MAC_ADDR;
memcpy(msg_addr, addr,6);
ret_val = mbx->ops.write_posted(hw, msbug, 3);
Setting Multicast Address
消息ID:IXGBE_VF_SET_MULTICAST
当VF驱动需要设置一个多播地址来过滤达到的包时就会发送该消息。
实例:
文件:ixgbe_vf.c
函数:ixgbe_update_mc_addr_list_vf
cnt = (mc_addr_count > 30) ? 30 : mc_addr_count;
msgbuf[0] = IXGBE_VF_SET_MULTICAST;
msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT;
for( i = 0; i < cnt; i++)
{
vector = ixgbe_mta_vector(hw, next(hw, &mc_addr_list, &vmdq));
hw_dbg(hw, "Hash value = 0x%03x\n",vector);
vector_list[i] = (u16) vector;
}
mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE, 0);
Setting VLAN Filter
消息ID:IXGBE_VF_VLAN
VF驱动想要设置一个VLAN 标识来过滤到达的包就会发送该消息
实例:
文件:ixgbe_vf.c
函数:ixgbe_set_vfta_vf
msgbuf[0] = IXGBE_VF_SET_VLAN;
msgbuf[1] = vlan;
msgbuf[0] |= vlan_on << IXGBE_VTMSGINFO_SHIFT;
mbx-ops.write_posted(hw, msgbuf, 2, 0);
PF to VF Mailbox Messages
Physical Function Driver
该驱动负责物理资源和针对VF配置的一些处理。
当驱动在探测发现设备的时候,在驱动初始化执行的众多任务中,有一项就是将自己注册为一个SR-IOV设备。
文件:ixgbe_main.c
函数:__devinit ixgbe_probe_vf
err = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
这个函数调用将82599注册为一个SR-IOV设备,表明支持特定数量的VF。
Default Configuration
在驱动初始化阶段进行了很多项默认配置。这些默认配置包括VF的个数,VF流量配置,VFMAC地址分配。
Assignment of Queue's to Pools
82599 PF 驱动 默认支持配置63个VF。每个池内有两个队列对与其相关,总共4个队列
文件:ixgbe_main.c
函数:ixgbe_up_complete
if ( adapter->flags & IXGBE_FLAG_SRIOV_ENABLED )
{
gpie &= ~IXGBE_GPIE_VTMODE_MASK;
gpie |= IXGBE_GPIE_VTMODE_64;
}
IXGBE_WRITE_REG(hw, IXGBE_GPID, gpie);
这段代码对PCIe 控制寄存(GCR_EXT-0x11050)器进行了配置,默认支持64个VF。
文件:ixgbe_main.c
函数:ixgbe_up_complete
if ( adapter->flags & IXGBE_FLGA_SRIOV_ENABLED)
{
gpie &= ~IXGBE_GPIE_VTMODE_MASK;
gpie |= IXGBE_GPIE_VTMODE_64;
}
IXGBE_WRITE_REG(hw, IXGBE_GPIE,gpie);
该代码片段配置 VT_Mode (15:14)比特,目的是对中断寄存器(GPIE-0x00898)进行配置.
Enabling VF to VF Bridging
VF 到 VF 的桥接在函数ixgbe_configure_rx() 函数中实现,该函数位于ixgbe_main.c
该函数使能了PF DMA 传输交换控制寄存器(PFDTXGSWC)的回环使能位(LBE)
文件:ixgbe_main.c
函数:ixgbe_configure_rx
#ifdef CONFIG_PCI_IOV
if( adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
{
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
ixgbe_set_vmolr(hw, adapter->num_vfs);
}
#endif
该代码片段同时也使能了VF的流量,通过ixgbe_set_vmolr函数的调用。
Default Pool
当一些包不会送到某个VF则会送到默认池去处理。这个池资源是为PF准备的。默认池是不分配给VF的池。如果有32个池资源已经进行了配置,第33个池就会配配置为默认池。
文件:ixgbe_main.c
函数:ixgbe_configure_rx
if(adapter->num_vfs )
{
vt_reg_bits &= ~IXGBE_VT_CTL_POOL_MASK;
vt_reg_bits |= (adapter->num_vfs << IXGBE_VT_CTL_POOL_SHIFT);
}
u32 vt_reg;
u32 vt_reg_bits;
if ( hw->mac.type = ixgbe_mac_82599EB)
{
vt_reg = IXGBE_VT_CTL;
vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN | IXGBE_VT_CTL_REPLEN
if ( adapter->num_vfs )
{
vt_reg_bits &= ~IXGBE_VT_CTL_POOL_MASK;
vt_reg_bits |= (adapter->num_vfs << IXGBE_VT_CTL_POOL_SHIFT);
}
}
else {
vt_reg = IXGBE_VMD_CTL;
vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN;
}
vmdctl = IXGBE_READ_REG(hw, vt_reg);
IXGBE_WRITE_REG(hw, vt_reg, vmdctl | vt_reg_bits);
驱动操作PFVTCTL(0x051B0)寄存器来配置默认池。主要操作DEF_PF 位(12:7)
Replication Enable
Broadcast Accept Mode
Accept Packet Matching PFUTA Table
这里允许VF接收一个域PF 单波表(PFUTA 0x0F400)中某个单波地址入口匹配的包。
文件:ixgbe_sriov.c
函数:ixgbe_set_vmolr
u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
vmolr |= (IXGBE_VMOLR_AUPE | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE |
IXGBE_VMOLR_BAM);
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
驱动操作PF VM L2 控制寄存器(PFVML2FLT 0x0F000 + 4 *n [n=0..63] )的ROPE域(第26比特)使能作者禁止VF 接收赖在PFUTA表的包。
Accept Packets Matching MTA Table
该功能允许VF接收在多播表阵列(UTA 0xA000)中匹配多播地址入口的包。
默认是接收。
文件:ixgbe_sriov.c
函数:ixgbe_set_vmolr
u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
vmolr |= (IXGBE_VMOLR_AUPE | IXGBE_VMOLR_ROMPE |
IXGBE_VMOLR_ROPE | IXGBE_VMOLR_BAM);
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
驱动操作 PF VM L2 控制寄存器(PFVML2FLT 0x0F000 + 4 *n [n = 0..63]的ROMPE域(第25bit)注册使能或者禁止接收来自MTA 表的包。
Accept Untagged Packets Enable
这种方式允许VF接收一个MAC地址匹配但是VLAN 标识不一定要匹配的包。
默认情况下,未加标识的包的接收功能已经使能。
文件:ixgbe_sriov.c
函数:ixgbe_set_vmolr
u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
vmolr |= ( IXGBE_VMOLR_AUPE | IXGBE_VMOLR_ROMPE |
IXGBE_VMOLR_ROPE | IXGBE_VMOLR_BAM);
IXGBE_WRTIE_REG(hw, IXGBE_VMOLR(vf),vmolr);
驱动操作PF VM L2 控制寄存器(PFVML2FLT 0x0F000 + 4*n [n=0..63])注册使能或禁止VF接收未加标识的包
Strip VLAN Tag for Incoming Packets
这允许一个VF 剥去一个通过L2 过滤传过来的包的VLAN 标识
默认情况下,这项功能是开启的。
文件:ixgbe_main.c
函数:ixgbe_vlan_rx_register
for( i = 0; i < adpater->num_rx_queues; i++)
{
j = adpter->rx_ring[i]->reg_idx;
ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(j));
ctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(j), ctrl);
}
驱动操作接收描述符控制寄存器(RXDCTL[n] (0x01208 + 0x40*n, n= 0..63 and 0x0D028 + 0x40*(n-64)), n=64..127; RW)的VLAN 模式使能位(第30bit)注册使能或禁止剥除到来包的VLAN 标识。
VF MAC 地址赋值
PF 驱动使用random_ether_add()函数(由内核提供【哪个内核,操作系统还是Hypervisor?】)动态的给每一个VF赋予一个MAC地址。下面的代码片段是一个展示示例:
文件:ixgbe_sriov.c
函数:ixgbe_vf_configuration
random_ether_addr(vf_mac_addr);
memcpy( adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr,6);
__devinit ixgbe_probe() 例程为每一个创建的VF调用ixgbe_vf_configuration() 一次。VF获得MAC地址当进行功能级的复位时,VF通过信箱发送IXGBE_VF_RESET消息到PF。PF发回VF MAC地址作为回复。
此外,VF驱动亦可以指定自己的MAC地址使用IXGBE_VF_SET_MAC消息。