Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

CentOS7でSR-IOV設定

CentOS7でSR-IOV設定を行ったため、その手順を記載しておきます。

1.環境

筐体:ProLiant DL360e Gen8
System ROM:P73 08/02/2014
NIC:Intel X540-AT2 ※1
OS:CentOS7.4
Installed Environment Groups:サーバー (GUI 使用) (graphical-server-environment) ※2

※1
X540-T2として販売されているもので、HP純正ではなくAmazonで購入したOEM提供のものです。
※2
最小限のインストール (minimal)の場合、lspciの追加インストールなどが必要なので、graphical-server-environmentを使用しています。
※3
BIOS上でSR-IOVを有効化する方法はHPガイドを参照してください。なお、私はBIOSでSR-IOVを有効化した後、OSをインストールしています。しかし、OSインストール後に、BIOS上でSR-IOVを有効化しても可能だ、という記事を見つけましたが、真相は確かめていません。

2.物理状態の確認

(1)PCIeのSlot1にX540を挿入していること。
HPガイドの14ページ目にARI(Alternative Routing ID Interpretation)機能がサポートしていないSlot番号が記載されています。ARI機能をサポートしていないPCIeのSlotにX540などSR-IOV対応NICを挿入しても、SR-IOVが有効化できない場合があるため事前に確認しておきましょう。


(2)X540のリンクが10Gbpsでリンクアップしていること。
UTPなので1Gbpsでもリンクアップした状態にすることは可能ですが、SR-IOVの有効化を行うと1Gbpsではダメだというメッセージがdmesgに表示されます。
RJ45の10Gスイッチがすぐに用意できない場合
X540-AT2は10Gポートが2ポートあるため、ループバック接続(X540-AT2の1ポート目と2ポート目をUTPで直結)にて対応しました。

3.NIC状態の確認

(1)NICが認識されていること。

# lspci |grep Eth
02:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.2 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.3 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
08:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)

(2)10000Mb/s(10Gbps)でリンクアップしていること。

# ethtool ens1f0
Settings for ens1f0:
Supported ports: [ TP ]
Supported link modes: 100baseT/Full
1000baseT/Full
10000baseT/Full
Supported pause frame use: Symmetric
Supports auto-negotiation: Yes
Advertised link modes: 100baseT/Full
1000baseT/Full
10000baseT/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: Yes
Speed: 10000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: external
Auto-negotiation: on
MDI-X: Unknown
Supports Wake-on: d
Wake-on: d
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes

4.iommuの有効化

SR-IOVを有効化する準備として、iommuを有効にします。

vi /etc/sysconfig/grub

以下のようにGRUB_CMDLINE_LINUX=行の最後に、intel_iommu=on iommu=ptを追加

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt"

以下のコマンドでgrub2.cfgに反映

grub2-mkconfig -o /etc/grub2.cfg

出力例

# grub2-mkconfig -o /etc/grub2.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-693.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-693.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-0b4fb8fdbcf94115af972373627c94dc
Found initrd image: /boot/initramfs-0-rescue-0b4fb8fdbcf94115af972373627c94dc.img
done

5.SR-IOVの有効化設定

起動時にVFがPCIバイスとして認識されるように設定します。

vi /etc/rc.local

最終行に以下の内容を追加

echo 2 > /sys/class/net/ens1f0/device/sriov_numvfs
echo 1 > /sys/class/net/ens1f1/device/sriov_numvfs
exit 0

上記について補足
ens1f0はX540のインターフェース名なので、ご自身の環境に合わせて変更してください。

X540-AT2は2ポートあるため、1ポート目がens1f0、2ポート目がens1f1となります。
上記設定の場合、ens1f0にVFを2ポート、ens1f1にVFを1ポートとする設定となります。

私の環境でmodprobeを行ったところ、以下の結果となってしまったため、上記の設定を行いました。

# modprobe ixgbe max_vfs=2,1
modprobe: ERROR: could not insert 'ixgbe': Invalid argument

但し、RedhatのDocを読む限り、上記設定はよろしくないそうなので、別な方法を模索しています。
理由は、systemctlになってからOS起動時に各種サービスなどが並列で実行されるらしく、rc.localも例外ではないそうなので、X540のドライバが読み込まれる前にrc.localが実行されると予期せぬエラーを引き起こす可能性があるため、だそうです。

6.rc.localに実行権限を付与

Defaultでは実行権限がないため、起動時に実行されるよう権限を付与します。

chmod +x /etc/rc.d/rc.local

7.ここで一旦再起動

reboot
もしくは
shutdown -r now

8.再びNIC状態の確認

Virtual Functionが追加表示されていればOK
★の付いてる行がVF(Virtual Function)

# lspci |grep Eth
02:00.0 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.1 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.2 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
02:00.3 Ethernet controller: Intel Corporation I350 Gigabit Network Connection (rev 01)
08:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
08:10.0 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01) ★1
08:10.1 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01) ★2
08:10.2 Ethernet controller: Intel Corporation X540 Ethernet Controller Virtual Function (rev 01) ★3

上記出力だけだと、どのVFが、どのPCIバス、スロット、ファンクション番号に紐づいているかがわからないため、★の横に数字を記載しています。
また後述するMACアドレス固定の項も併せて参照してください。

上記について補足

再起動後にVFが作成されなかった場合、dmesg上に以下のエラーが出力されている可能性があります。
 kernel: igb 0000:02:00.1: not enough MMIO resources for SR-IOV

このときの対処方法

vi /etc/sysconfig/grub

以下のようにGRUB_CMDLINE_LINUX=行の最後に、pci=reallocを追加して再起動。

GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on iommu=pt pci=realloc"

本来、BIOSがVF用リソース割り当てを行うそうなのですが、BIOSNICの組み合わせによって、うまくいかない場合があるそうです。このため上記設定を行うことによりカーネルがVF用リソース割り当てを行えるようになるそうです。

9.modprobeのblacklistへの追加

ixgbevfを外すことによりホストOS上でVFがNICとして認識されるのを防ぎます。
但し、ホストOS上ではPCIバイスとして認識しているため、ゲストOSにアタッチすることは可能です。

vi /lib/modprobe.d/dist-blacklist.conf

最終行に以下の内容を追加

# ixgbevf driver
blacklist ixgbevf

10.VFのMACアドレス固定設定

上記9.の設定を実施するとVFのMACアドレスはオール0(00:00:00:00:00:00)となります。
このため、任意の被らないMACアドレスを指定します。

vi /etc/rc.d/rc.local

最終行に以下の内容を追加

ip link set ens1f0 vf 0 mac 00:11:22:33:44:55
ip link set ens1f0 vf 1 mac 00:11:22:33:44:56
ip link set ens1f1 vf 0 mac 00:11:22:33:44:57

上述した通り、VFとPCIバス番号などの紐付きがわからないため、
以下に紐づきがわかるよう★の横に記載しておきます。

ip link set ens1f0 vf 0 mac 00:11:22:33:44:55 ★1 08:10.0
ip link set ens1f0 vf 1 mac 00:11:22:33:44:56 ★3 08:10.2
ip link set ens1f1 vf 0 mac 00:11:22:33:44:57 ★2 08:10.1

今のところ、これを把握するには、VFをゲストOSにアタッチ後、ゲストOS上にてip link showなどでMACアドレスを確認する以外、方法はないのかな?と悩んでいます。

最後に

SR-IOV設定のHow toサイトは色々見て回ったのですが、H/WとOSの環境情報が詳細に記載されているサイトが少なかったため、環境をしっかりと記載してみました。一度でも成功すれば、どうってことない事だったりするものですが、一度も成功したことが無いときは、何が原因なのか?切り分けがつかない場合があるため、環境情報も大切だなと実感しています。