CentOS8によるvDPA(virtio data path acceleration)の設定方法について記載しました。*1
vDPAは、SR-IOVの性能とVirtIOの柔軟性を兼ね備えたフレームワークです。
クラウドネイティブNWを見据え、今後が期待されている技術であり、Linux Kernel 5.7.0より正式にマージされています。
vDPAの詳細はThe official Red Hat blogを参照してください。
本ブログでは、vhost_vdpaモジュールを使用したVM(仮想マシン)間通信の設定方法について記載していきます。
2021/06/01 Update
libvirtdによるVM起動方法を追記しました。
以下は関連記事の一覧となります。
1.構成
1-1.環境
IA server : ProLiant DL360p Gen8 or DL360 Gen9 System ROM : P71 01/22/2018 NIC : Mellanox ConnectX-6 Dx (MCX623106AS-CDAT) OS : CentOS8.3(2011) Kernel : 5.11.11-1.el8.elrepo.x86_64 Installed Environment Groups : @^graphical-server-environment @container-management @development @virtualization-client @virtualization-hypervisor @virtualization-tools Mellanox OFED : v5.2-2.2.0.0 qemu-kvm : v6.0.0-rc1 DPDK : v21.02 ovs : v2.14.1 libvirtd : v7.4.0-rc2 2021/06/01update
1-3.全体構成
DAC(Direct Attached Cable)を使用してループ接続します。 *2
fig.1
fig.1は簡易的に記載しており、内部アーキテクチャは省略しています。このため、実際は以下の構成をイメージして頂ければと思います。
fig.2
Red HatのBlogより引用
vDPA kernel framework part 3: usage for VMs and containers
オレンジ色点線の(A)(B)が、それぞれfig.1とfig.2に対応しています。
さらに、fig.2においては、実際のトラフィックフローを青文字と赤文字で記載しています。*3
fig.2において、SR-IOVのPFとVFをそれぞれ記載していますが、これに加えて「VF rep」を記載しています。PFとVF repのbsf(Bus, Slot, Function)番号が同一である点も注意が必要です。
PF | VF0 | VF0 rep |
ens2f0 | ens2f0v0 | ens2f0_0 |
07:00.0 | 07:00.2 | 07:00.0 |
rep=representorは、SR-IOVにおけるswtichdevモード特有のインターフェースで、swtichdevモードを有効化することにより作成されます。
また、swtichdevモードに対して、従来のSR-IOV VFをlegacyモードと呼び、明示的に別けて使用する必要があります。加えて、ConnectX-6 Dxでは、vDPA HW offloadを有効化するために、swtichdevモードが必須要件となっています。
2.事前準備
特に記載しませんが、SELinux無効化、FW無効化、NTP時刻同期設定は事前に行っています。
2-1.HugePageとIOMMUの有効化
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ default_hugepagesz=1G hugepagesz=1G hugepages=16\"/g" /etc/default/grub sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub grub2-mkconfig -o /etc/grub2.cfg
次にHugePageのマウント設定を実施しておきます。次回OS起動時に自動マウントされます。
vi /etc/fstab nodev /dev/hugepages hugetlbfs pagesize=1GB 0 0
2-2.SR-IOV VFの設定
SR-IOV VFの設定を実施します。VF数を増やしても問題ありませんが、ここでは説明をシンプルにするため、VF数「1」としています。加えて、MACアドレスの設定は必須です。*4
vi /etc/rc.local echo 1 > /sys/class/net/ens2f0/device/sriov_numvfs echo 1 > /sys/class/net/ens2f1/device/sriov_numvfs sleep 1 ip link set ens2f0 vf 0 mac 00:11:22:33:44:00 ip link set ens2f1 vf 0 mac 00:11:22:33:44:10 sleep 1 exit 0 chmod +x /etc/rc.d/rc.local
2-3.Mellanoxドライバ(OFED)のインストール
isoファイルはMellanoxのサイトからDLしてください。Mellanox Download Site
DLしたisoファイルは、/root/tmp/に保存してください。
以下のコマンドにて、Mellanoxドライバをインストールしますが、ovs v2.14.1も同時にインストールされます。
dnf -y install tcl tk unbound && \ mount -t iso9660 -o loop /root/tmp/MLNX_OFED_LINUX-5.2-2.2.0.0-rhel8.3-x86_64.iso /mnt && \ /mnt/mlnxofedinstall --upstream-libs --dpdk --ovs-dpdk --with-mft --with-mstflint
インストールが完了したら、再起動してください。
reboot
再起動が完了したら、HugePageを確認します。
cat /proc/meminfo | grep Huge grep hugetlbfs /proc/mounts [root@c83g155 ~]# cat /proc/meminfo | grep Huge AnonHugePages: 452608 kB ShmemHugePages: 0 kB FileHugePages: 0 kB HugePages_Total: 16 HugePages_Free: 16 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 1048576 kB Hugetlb: 16777216 kB [root@c83g155 ~]# grep hugetlbfs /proc/mounts nodev /dev/hugepages hugetlbfs rw,relatime,pagesize=1024M 0 0
3.Kernelアップデート
2021年4月8日現在、vDPA関連モジュールは高い頻度で更新されていますので、最新のKernelをインストールします。
3-1.elrepoのインストール
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org dnf -y install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
3-2.Kernelのインストール
dnf list installed | grep kernel dnf -y --enablerepo=elrepo-kernel install kernel-ml kernel-ml-devel dnf list installed | grep kernel reboot
現在インストール済みのKernelを確認
kernel-ml, kernel-ml-develをインストール*5
インストール済みKernelの確認
再起動
3-3.Kernel headersなどのインストール
uname -r dnf -y swap --enablerepo=elrepo-kernel kernel-headers -- kernel-ml-headers && \ dnf -y remove kernel-tools kernel-tools-libs && \ dnf -y --enablerepo=elrepo-kernel install kernel-ml-tools kernel-ml-tools-libs dnf list installed | grep kernel
現在起動中のKernel Version確認
kernel-headersのインストール
既存のkernel-tools kernel-tools-libsの削除
kernel-tools kernel-tools-libsのインストール
インストール済みKernelの確認
以下の出力になっていればOKです。
[root@c83g155 ~]# dnf list installed | grep kernel kernel.x86_64 4.18.0-240.el8 @anaconda kernel-core.x86_64 4.18.0-240.el8 @anaconda kernel-devel.x86_64 4.18.0-240.el8 @anaconda kernel-ml.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-core.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-devel.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-headers.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-modules.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-tools.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-ml-tools-libs.x86_64 5.11.11-1.el8.elrepo @elrepo-kernel kernel-modules.x86_64 4.18.0-240.el8 @anaconda kmod-kernel-mft-mlnx.x86_64 4.16.1-1.rhel8u3 @System kmod-mlnx-ofa_kernel.x86_64 5.2-OFED.5.2.2.2.0.1.rhel8u3 @System mlnx-ofa_kernel.x86_64 5.2-OFED.5.2.2.2.0.1.rhel8u3 @System mlnx-ofa_kernel-devel.x86_64 5.2-OFED.5.2.2.2.0.1.rhel8u3 @System
4.qemuとlibvirtdのビルド 2021/06/01update
4-1.各種リポジトリの有効化
sed -i -e 's/enabled=0/enabled=1/g' /etc/yum.repos.d/CentOS-Linux-PowerTools.repo && \ dnf -y install https://pkgs.dyn.su/el8/base/x86_64/raven-release-1.0-1.el8.noarch.rpm && \ sed -i -e 's/enabled=0/enabled=1/g' /etc/yum.repos.d/raven.repo
4-2.必要なパッケージのインストール
qemuとlibvirtdに加えて、dpdkのビルドで必要とされるパッケージも合わせてインストールしています。
dnf -y install cmake gcc libnl3-devel libudev-devel make numactl numactl-devel \ pkgconfig valgrind-devel pandoc libibverbs libmlx5 libmnl-devel meson ninja-build \ glibc-utils glib2 glib2-devel pixman pixman-devel zlib zlib-devel rpcgen python3-docutils \ gnutls gnutls-devel libxml2-devel yajl-devel libtirpc-devel libudev-devel libpciaccess-devel \ usbredir-devel spice-server-devel && \ wget https://cbs.centos.org/kojifiles/packages/pyelftools/0.26/1.el8/noarch/python3-pyelftools-0.26-1.el8.noarch.rpm && \ dnf -y localinstall python3-pyelftools-0.26-1.el8.noarch.rpm && \ dnf -y install https://rpmfind.net/linux/centos/8-stream/PowerTools/x86_64/os/Packages/meson-0.55.3-3.el8.noarch.rpm
4-3.qemuのビルド
cd /usr/src && \ git clone https://github.com/qemu/qemu.git && \ cd qemu/ && \ git checkout v6.0.0-rc1 && \ mkdir build && \ cd build/ && \ ../configure --enable-vhost-vdpa --target-list=x86_64-softmmu && \ make -j && \ make install
インストール後のVersion確認
/usr/local/bin/qemu-system-x86_64 --version [root@c83g155 ~]# /usr/local/bin/qemu-system-x86_64 --version QEMU emulator version 5.2.91 (v6.0.0-rc1) Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
4-4.libvirtdのビルド
cd /usr/src && \ git clone https://github.com/libvirt/libvirt.git && \ cd libvirt/ && \ git checkout v7.4.0-rc2 && \ meson build && \ ninja -C build && \ ninja -C build install
インストール後のVersion確認
libvirtd -V [root@c83g155 ~]# libvirtd -V libvirtd (libvirt) 7.4.0
4-5.qemu実行Pathの変更
mv /usr/libexec/qemu-kvm /usr/libexec/qemu-kvm.org ln -s /usr/local/bin/qemu-system-x86_64 /usr/libexec/qemu-kvm
4-6.qemu実行ユーザの変更
vi /usr/local/etc/libvirt/qemu.conf user = "root" #comment out group = "root" #comment out
4-7.libvirt-sockの設定変更
青文字箇所を追記
vi /etc/rc.local echo 1 > /sys/class/net/ens2f0/device/sriov_numvfs echo 1 > /sys/class/net/ens2f1/device/sriov_numvfs sleep 1 ip link set ens2f0 vf 0 mac 00:11:22:33:44:00 ip link set ens2f1 vf 0 mac 00:11:22:33:44:10 sleep 1 mkdir /var/run/libvirt ln -s /var/local/run/libvirt/libvirt-sock /var/run/libvirt/libvirt-sock sleep 1 exit 0
5.dpdkのビルド
5-1.dpdkのビルド
cd /usr/src/ && \ git clone git://dpdk.org/dpdk && \ cd dpdk && \ git checkout v21.02 && \ meson -Dexamples=all build && \ ninja -C build && \ ninja -C build install
5-2.dpdk関連ライブラリのリンク
viで新規ファイルを作成し、libのPathを記載してください。
vi /etc/ld.so.conf.d/libdpdk.conf /usr/src/dpdk/build/lib
ldconfigを実行後、libがリンクされたことを確認してください。
ldconfig ldconfig -p |grep dpdk
以下のようにポイントされていればOKです。
[root@c83g155 dpdk]# ldconfig -p |grep dpdk librte_vhost.so.21 (libc6,x86-64) => /usr/src/dpdk/build/lib/librte_vhost.so.21 librte_vhost.so (libc6,x86-64) => /usr/src/dpdk/build/lib/librte_vhost.so librte_timer.so.21 (libc6,x86-64) => /usr/src/dpdk/build/lib/librte_timer.so.21
ここで、一旦再起動しておきます。
reboot
6.SR-IOV switchdev modeへ変更
6-1.現在の動作モードを確認
lshw -businfo -c network devlink dev eswitch show pci/0000:07:00.0 devlink dev eswitch show pci/0000:07:00.1
PCIデバイスのbsf(bus, slot, function)番号を確認
07:00.0(ens2f0)のステータス確認
07:00.1(ens2f1)のステータス確認
以下のように出力されます。
[root@c83g155 ~]# lshw -businfo -c network Bus info Device Class Description ======================================================== pci@0000:04:00.0 ens1f0 network 82599ES 10-Gigabit SFI/SFP+ Network Connection pci@0000:04:00.1 ens1f1 network 82599ES 10-Gigabit SFI/SFP+ Network Connection pci@0000:03:00.0 eno1 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.1 eno2 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.2 eno3 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.3 eno4 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:07:00.0 ens2f0 network MT2892 Family [ConnectX-6 Dx] pci@0000:07:00.1 ens2f1 network MT2892 Family [ConnectX-6 Dx] pci@0000:07:00.2 ens2f0v0 network ConnectX Family mlx5Gen Virtual Function pci@0000:07:01.2 ens2f1v0 network ConnectX Family mlx5Gen Virtual Function [root@c83g155 ~]# devlink dev eswitch show pci/0000:07:00.0 pci/0000:07:00.0: mode legacy inline-mode none encap disable [root@c83g155 ~]# devlink dev eswitch show pci/0000:07:00.1 pci/0000:07:00.1: mode legacy inline-mode none encap disable
6-2.動作モードの変更
bsf番号が微妙に異なっている点に注意してください。*6
echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \ echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/unbind && \ devlink dev eswitch set pci/0000:07:00.0 mode switchdev && \ devlink dev eswitch set pci/0000:07:00.1 mode switchdev && \ echo 0000:07:00.2 > /sys/bus/pci/drivers/mlx5_core/bind && \ echo 0000:07:01.2 > /sys/bus/pci/drivers/mlx5_core/bind
VFのmlx5_coreドライバをアンバインドします。
07:00.2 | ens2f0v0 |
07:01.2 | ens2f1v0 |
PFの動作モードをswitchdevに変更します。
07:00.0 | ens2f0 |
07:00.1 | ens2f1 |
VFのmlx5_coreドライバを再バインドします。
07:00.2 | ens2f0v0 |
07:01.2 | ens2f1v0 |
6-3.変更後の動作モードを確認
devlink dev eswitch show pci/0000:07:00.0 devlink dev eswitch show pci/0000:07:00.1
switchdev モードに変更されました。
[root@c83g155 ~]# devlink dev eswitch show pci/0000:07:00.0 pci/0000:07:00.0: mode switchdev inline-mode none encap enable [root@c83g155 ~]# devlink dev eswitch show pci/0000:07:00.1 pci/0000:07:00.1: mode switchdev inline-mode none encap enable
VF Representerが追加されています。
[root@c83g155 ~]# lshw -businfo -c network Bus info Device Class Description ======================================================== pci@0000:04:00.0 ens1f0 network 82599ES 10-Gigabit SFI/SFP+ Network Connection pci@0000:04:00.1 ens1f1 network 82599ES 10-Gigabit SFI/SFP+ Network Connection pci@0000:03:00.0 eno1 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.1 eno2 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.2 eno3 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:03:00.3 eno4 network NetXtreme BCM5719 Gigabit Ethernet PCIe pci@0000:07:00.0 ens2f0 network MT2892 Family [ConnectX-6 Dx] pci@0000:07:00.1 ens2f1 network MT2892 Family [ConnectX-6 Dx] pci@0000:07:00.2 ens2f0v0 network ConnectX Family mlx5Gen Virtual Function pci@0000:07:01.2 ens2f1v0 network ConnectX Family mlx5Gen Virtual Function pci@0000:07:00.0 ens2f0_0 network Ethernet interface pci@0000:07:00.1 ens2f1_0 network Ethernet interface
さらに、NICのHW offload機能が有効化されていることも確認します。
ethtool -k ens2f0 |grep tc ethtool -k ens2f1 |grep tc [root@c83g155 ~]# ethtool -k ens2f0 |grep tc tcp-segmentation-offload: on tx-tcp-segmentation: on tx-tcp-ecn-segmentation: off [fixed] tx-tcp-mangleid-segmentation: off tx-tcp6-segmentation: on hw-tc-offload: on [root@c83g155 ~]# ethtool -k ens2f1 |grep tc tcp-segmentation-offload: on tx-tcp-segmentation: on tx-tcp-ecn-segmentation: off [fixed] tx-tcp-mangleid-segmentation: off tx-tcp6-segmentation: on hw-tc-offload: on
7.ovs-dpdkとVMの設定
7-1.全体の流れ ~概要~
以下のfig.1に記載されている(1)-(9)の順に設定していきます。
fig.1
7-2.全体の流れ ~コマンドのみ~
以下のコマンドを投入していきます。
詳細な解説は後述しますが、解説が不要な方はコマンドだけを実行してください。
1.vhost_vdpaモジュールの有効化
(1)
modprobe vhost_vdpa
2.ovsの初期設定
systemctl start openvswitch
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true other_config:tc-policy=none
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024,1024
ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true
ovs-vsctl set Open_vSwitch . other_config:dpdk-extra=" \
-w 0000:07:00.0,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0 \
-w 0000:07:00.1,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0"
systemctl restart openvswitch
3.br30-ovsの設定
(2)
ovs-vsctl add-br br30-ovs -- set bridge br30-ovs datapath_type=netdev
(3)
ovs-vsctl add-port br30-ovs ens2f0 -- set Interface ens2f0 type=dpdk options:dpdk-devargs=0000:07:00.0
(4)
ovs-vsctl add-port br30-ovs ens2f0_0 -- set Interface ens2f0_0 type=dpdk options:dpdk-devargs=0000:07:00.0,representor=[0]
4.br31-ovsの設定
(5)
ovs-vsctl add-br br31-ovs -- set bridge br31-ovs datapath_type=netdev
(6)
ovs-vsctl add-port br31-ovs ens2f1 -- set Interface ens2f1 type=dpdk options:dpdk-devargs=0000:07:00.1
(7)
ovs-vsctl add-port br31-ovs ens2f1_0 -- set Interface ens2f1_0 type=dpdk options:dpdk-devargs=0000:07:00.1,representor=[0]
A.qemuの場合
5.仮想マシンc77g153の設定と起動
(8)
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-m 8G \
-hda /var/lib/libvirt/images/c77g1532.qcow2 \
-netdev type=vhost-vdpa,vhostdev=/dev/vhost-vdpa-0,id=vhost-vdpa0 \
-device virtio-net-pci,netdev=vhost-vdpa0,page-per-vq=on,iommu_platform=on,disable-legacy=on \
-nographic \
2>&1 | tee vm153.log
6.仮想マシンc77g159の設定と起動
(9)
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-m 8G \
-hda /var/lib/libvirt/images/c77g1592.qcow2 \
-netdev type=vhost-vdpa,vhostdev=/dev/vhost-vdpa-1,id=vhost-vdpa1 \
-device virtio-net-pci,netdev=vhost-vdpa1,page-per-vq=on,iommu_platform=on,disable-legacy=on \
-nographic \
2>&1 | tee vm159.log
B.libvirtdの場合 2021/06/01update
5.仮想マシンc77g153の設定と起動
(8)
virsh edit c77g153
<interface type='vdpa'>
<source dev='/dev/vhost-vdpa-0'/>
</interface>
6.仮想マシンc77g159の設定と起動
(9)
virsh edit c77g159
<interface type='vdpa'>
<source dev='/dev/vhost-vdpa-1'/>
</interface>
7-3.vhost_vdpaモジュールの有効化:(1)
modprobe vhost_vdpa コマンドの実行前と実行後の変化を確認していきます。
modprobe vhost_vdpa実行前
lsmod |grep vd ls -Fal /dev ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa [root@c83g155 ~]# lsmod |grep vd mlx5_vdpa 45056 0 vhost_iotlb 16384 2 vhost,mlx5_vdpa vdpa 16384 1 mlx5_vdpa mlx5_core 1216512 2 mlx5_vdpa,mlx5_ib [root@c83g155 ~]# ls -Fal /dev total 0 drwxr-xr-x 22 root root 3660 Apr 8 00:02 ./ dr-xr-xr-x. 17 root root 244 Apr 7 20:30 ../ crw-r--r-- 1 root root 10, 235 Apr 7 23:28 autofs drwxr-xr-x 2 root root 160 Apr 7 23:28 block/ drwxr-xr-x 2 root root 100 Apr 7 23:28 bsg/ ============ s n i p ============ drwxr-xr-x 2 root root 60 Apr 7 23:28 vfio/ crw------- 1 root root 10, 127 Apr 7 23:28 vga_arbiter crw------- 1 root root 10, 137 Apr 7 23:28 vhci crw------- 1 root root 10, 238 Apr 7 23:28 vhost-net crw------- 1 root root 10, 241 Apr 7 23:28 vhost-vsock [root@c83g155 ~]# ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa ls: cannot access '/sys/bus/vdpa/drivers/vhost_vdpa': No such file or directory
modprobe vhost_vdpa実行後
modprobe vhost_vdpa lsmod |grep vd ls -Fal /dev ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa [root@c83g155 ~]# lsmod |grep vd vhost_vdpa 24576 0 vhost 57344 1 vhost_vdpa mlx5_vdpa 45056 0 vhost_iotlb 16384 3 vhost_vdpa,vhost,mlx5_vdpa vdpa 16384 2 vhost_vdpa,mlx5_vdpa irqbypass 16384 2 vhost_vdpa,kvm mlx5_core 1216512 2 mlx5_vdpa,mlx5_ib [root@c83g155 ~]# ls -Fal /dev total 0 drwxr-xr-x 22 root root 3660 Apr 8 00:02 ./ dr-xr-xr-x. 17 root root 244 Apr 7 20:30 ../ crw-r--r-- 1 root root 10, 235 Apr 7 23:28 autofs drwxr-xr-x 2 root root 160 Apr 7 23:28 block/ drwxr-xr-x 2 root root 100 Apr 7 23:28 bsg/ ============ s n i p ============ drwxr-xr-x 2 root root 60 Apr 7 23:28 vfio/ crw------- 1 root root 10, 127 Apr 7 23:28 vga_arbiter crw------- 1 root root 10, 137 Apr 7 23:28 vhci crw------- 1 root root 10, 238 Apr 7 23:28 vhost-net crw------- 1 root root 240, 0 Apr 8 00:06 vhost-vdpa-0 crw------- 1 root root 240, 1 Apr 8 00:06 vhost-vdpa-1 crw------- 1 root root 10, 241 Apr 7 23:28 vhost-vsock [root@c83g155 ~]# ls -Fal /sys/bus/vdpa/drivers/vhost_vdpa total 0 drwxr-xr-x 2 root root 0 Apr 8 00:06 ./ drwxr-xr-x 3 root root 0 Apr 7 23:49 ../ --w------- 1 root root 4096 Apr 8 00:07 bind lrwxrwxrwx 1 root root 0 Apr 8 00:07 module -> ../../../../module/vhost_vdpa/ --w------- 1 root root 4096 Apr 8 00:06 uevent --w------- 1 root root 4096 Apr 8 00:07 unbind lrwxrwxrwx 1 root root 0 Apr 8 00:07 vdpa0 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:00.2/vdpa0/ lrwxrwxrwx 1 root root 0 Apr 8 00:07 vdpa1 -> ../../../../devices/pci0000:00/0000:00:03.0/0000:07:01.2/vdpa1/
上記の出力結果より、以下のことが確認できます。
- /dev/vhost-vdpa-0と/dev/vhost-vdpa-1がvhost_vdpaデバイスとして認識されている
- 0000:07:00.2/vdpa0と0000:07:01.2/vdpa1がvhost_vdpaドライバで制御されている
7-4.ovsの初期設定
ovsは、既にインストール済みなので*7、systemctlからサービスをスタートします。
systemctl start openvswitch
ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true other_config:tc-policy=none
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem=1024,1024
ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true
ovs-vsctl set Open_vSwitch . other_config:dpdk-extra=" \
-w 0000:07:00.0,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0 \
-w 0000:07:00.1,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0"
systemctl restart openvswitch
ovsサービスの起動
dpdkの初期化
HW offloadとtc-policyの設定
メモリ割当て
vhostのIOMMU設定
representerの設定
ovsサービスの再起動(上記設定を反映させるため)
以下のコマンドで設定内容を確認します。
ovs-vsctl get Open_vSwitch . other_config [root@c83g155 ~]# ovs-vsctl get Open_vSwitch . other_config {dpdk-extra=" -w 0000:07:00.0,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0 -w 0000:07:00.1,representor=[0],dv_flow_en=1,dv_esw_en=1,dv_xmeta_en=0", dpdk-init="true", dpdk-socket-mem="1024,1024", hw-offload="true", tc-policy=none, vhost-iommu-support="true"}
<補足1>
other_config:dpdk-extraについて、補足します。
lshw -businfo -c network の出力結果とother_config:dpdk-extra で設定したコマンドには、以下の対応関係があります。
0000:07:00.0 ens2f0_0 | -w 0000:07:00.0,representor=[0] |
0000:07:00.1 ens2f1_0 | -w 0000:07:00.1,representor=[0] |
<補足2>
other_config:tc-policyについて、補足します。
tc-policyは、以下のオプションが設定可能です。
none | adds a TC rule to both the software and the hardware (default) |
skip_sw | adds a TC rule only to the hardware |
skip_hw | adds a TC rule only to the software |
<補足3>
設定を削除したい場合は、以下のようにコマンドを実行してください。
dpdk-extra がキーとなっていますので、dpdk-initやhw-offloadなど、削除したい任意のキーを指定してください。
ovs-vsctl remove Open_vSwitch . other_config dpdk-extra
7-5.br30-ovsの設定:(2)(3)(4)
1つ目のブリッジを作成します。
(2) ovs-vsctl add-br br30-ovs -- set bridge br30-ovs datapath_type=netdev (3) ovs-vsctl add-port br30-ovs ens2f0 -- set Interface ens2f0 type=dpdk options:dpdk-devargs=0000:07:00.0 (4) ovs-vsctl add-port br30-ovs ens2f0_0 -- set Interface ens2f0_0 type=dpdk options:dpdk-devargs=0000:07:00.0,representor=[0]
(2)ブリッジの作成
(3)アップリンクの作成(PFを指定し、外部NW向けのインターフェースを設定)
(4)ダウンリンクの作成(VF Representerを指定し、VM向けのインターフェースを設定)
以下のコマンドで設定を確認します。
[root@c83g155 ~]# ovs-vsctl show 59a34ea2-ca80-48b9-8b14-a656c79bc451 Bridge br30-ovs datapath_type: netdev Port br30-ovs Interface br30-ovs type: internal Port ens2f0_0 Interface ens2f0_0 type: dpdk options: {dpdk-devargs="0000:07:00.0,representor=[0]"} Port ens2f0 Interface ens2f0 type: dpdk options: {dpdk-devargs="0000:07:00.0"} ovs_version: "2.14.1"
7-6.br31-ovsの設定:(5)(6)(7)
2つ目のブリッジを作成します。
(5) ovs-vsctl add-br br31-ovs -- set bridge br31-ovs datapath_type=netdev (6) ovs-vsctl add-port br31-ovs ens2f1 -- set Interface ens2f1 type=dpdk options:dpdk-devargs=0000:07:00.1 (7) ovs-vsctl add-port br31-ovs ens2f1_0 -- set Interface ens2f1_0 type=dpdk options:dpdk-devargs=0000:07:00.1,representor=[0]
(2)(3)(4)と同様です。
以下のコマンドで設定を確認します。青文字が追加された部分です。
[root@c83g155 ~]# ovs-vsctl show
59a34ea2-ca80-48b9-8b14-a656c79bc451
Bridge br31-ovs
datapath_type: netdev
Port ens2f1_0
Interface ens2f1_0
type: dpdk
options: {dpdk-devargs="0000:07:00.1,representor=[0]"}
Port ens2f1
Interface ens2f1
type: dpdk
options: {dpdk-devargs="0000:07:00.1"}
Port br31-ovs
Interface br31-ovs
type: internal
Bridge br30-ovs
datapath_type: netdev
Port br30-ovs
Interface br30-ovs
type: internal
Port ens2f0_0
Interface ens2f0_0
type: dpdk
options: {dpdk-devargs="0000:07:00.0,representor=[0]"}
Port ens2f0
Interface ens2f0
type: dpdk
options: {dpdk-devargs="0000:07:00.0"}
ovs_version: "2.14.1"
A. qemuの場合
7-7.仮想マシンc77g153の設定と起動:(8)
/var/lib/libvirt/images/にqcow2ファイルをアップロードしておいてください。
本ブログでは、CentOS7.7をインストールしたqcow2ファイルを予め準備していました。
(8) qemu-system-x86_64 \ -enable-kvm \ -cpu host \ -m 8G \ -hda /var/lib/libvirt/images/c77g1532.qcow2 \ -netdev type=vhost-vdpa,vhostdev=/dev/vhost-vdpa-0,id=vhost-vdpa0 \ -device virtio-net-pci,netdev=vhost-vdpa0,page-per-vq=on,iommu_platform=on,disable-legacy=on \ -nographic \ 2>&1 | tee vm153.log
type=vhost-vdpa | vhost-vdpaをtypeに指定できるようにするため、qemuをソースからビルドしています。 |
vhostdev=/dev/vhost-vdpa-0 | modprobe vhost_vdpa コマンドで生成されたvdpaデバイスを指定しています。 |
page-per-vq=on | virtqueueを使用するため必須の設定です |
iommu_platform=on | 詳細は確認できていませんが、fig.2よりPlatformIOMMUとvirtqueueのやり取りで使用するため必須の設定と思われます。 |
7-8.仮想マシンc77g159の設定と起動:(9)
qcow2ファイルやvdpaデバイス以外は、7-7と同様です。
(9) qemu-system-x86_64 \ -enable-kvm \ -cpu host \ -m 8G \ -hda /var/lib/libvirt/images/c77g1592.qcow2 \ -netdev type=vhost-vdpa,vhostdev=/dev/vhost-vdpa-1,id=vhost-vdpa1 \ -device virtio-net-pci,netdev=vhost-vdpa1,page-per-vq=on,iommu_platform=on,disable-legacy=on \ -nographic \ 2>&1 | tee vm159.log
B. libvirtdの場合2021/06/01update
7-7.仮想マシンc77g153の設定と起動:(8)
/var/lib/libvirt/images/にqcow2ファイルをアップロードしておいてください。
本ブログでは、CentOS7.7をインストールしたqcow2ファイルを予め準備していました。
加えて、一度virt-managerで仮想マシンを作成後、"virsh edit" コマンドで編集していきます。
VNCなどでホストOSにログインし、virt-managerを起動してください。
新規仮想マシンを作成する際、以下の[1]-[5]のデバイスを削除してください。*8
VM起動後、一旦shutdownします。
shutdown後、以下のようなデバイス構成になっていればOKです。
ここに記載されているNICはvDPAでは使用しませんが、sshできるようになるため、必要であれば管理用IPをアサインしてください。
shutdown後、virsh editコマンドで以下の設定を実施します。
(8) virsh edit c77g153 <devices> ============ s n i p ============ <interface type='vdpa'> <source dev='/dev/vhost-vdpa-0'/> </interface>
7-8.仮想マシンc77g159の設定と起動:(9)
/dev/vhost-vdpa-1以外は、7-7と同様です。
(9) virsh edit c77g159 <devices> ============ s n i p ============ <interface type='vdpa'> <source dev='/dev/vhost-vdpa-1'/> </interface>
8.動作確認
既に(8)(9)のコマンドを実行した結果、VM(c77g153 と c77g159)が起動済みですが、正常動作を確認するため、一旦シャットダウンしてください。
8-1.事前準備
ホストOS c83g155で5つのコンソールを準備してください。
ConsoleA | tail -f /var/log/messages | VM起動時に確認すべきログを参照するため |
ConsoleB | watch ovs-ofctl -O OpenFlow14 dump-ports br30-ovs | c77g153のパケットカウントを確認するため |
ConsoleC | watch ovs-ofctl -O OpenFlow14 dump-ports br31-ovs | c77g159のパケットカウントを確認するため |
ConsoleD | (8)のコマンドを実行 | 仮想マシンc77g153のコンソール用 |
ConsoleE | (9)のコマンドを実行 | 仮想マシンc77g159のコンソール用 |
libvirtdの場合2021/06/01update
ConsoleD | virsh start c77g153; virsh console c77g153 | 仮想マシンc77g153のコンソール用 |
ConsoleE | virsh start c77g159; virsh console c77g159 | 仮想マシンc77g159のコンソール用 |
8-2.VMの起動
VMを起動する前に、ConsoleA, B, Cでは上記のコマンドを実行しておいてください。
その後、(8)のコマンドを実行し、c77g153を起動します。
数秒待ってから、(9)のコマンドを実行し、c77g159を起動します。
c77g153 or c77g159からPingを飛ばしてください。
例として、fig.1に従い、c77g153から ping 192.168.30.159 -f を実行します。
fig.1
以下、出力結果です。注目する箇所は赤文字にしています。
ConsoleA
Apr 8 10:38:21 c83g155 dbus-daemon[2076]: [session uid=0 pid=2076] Activating via systemd: service name='org.freedesktop.Tracker1.Miner.Extract' unit='tracker-extract.service' requested by ':1.72' (uid=0 pid=2706 comm="/usr/libexec/tracker-miner-fs ") Apr 8 10:38:21 c83g155 systemd[1919]: Starting Tracker metadata extractor... Apr 8 10:38:21 c83g155 kernel: mlx5_core 0000:07:00.2: mlx5_vdpa_set_status:1786:(pid 5077): performing device reset Apr 8 10:38:21 c83g155 kvm[5088]: 1 guest now active Apr 8 10:38:21 c83g155 dbus-daemon[2076]: [session uid=0 pid=2076] Successfully activated service 'org.freedesktop.Tracker1.Miner.Extract' Apr 8 10:38:21 c83g155 systemd[1919]: Started Tracker metadata extractor. Apr 8 10:38:46 c83g155 kernel: mlx5_core 0000:07:00.2: mlx5_vdpa_handle_set_map:473:(pid 5086): memory map update Apr 8 10:38:51 c83g155 ovs-vswitchd[4998]: ovs|00001|dpif_netdev(revalidator17)|ERR|internal error parsing flow key skb_priority(0),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(6),packet_type(ns=0,id=0),eth(src=00:11:22:33:44:00,dst=01:00:5e:00:00:16),eth_type(0x0800),ipv4(src=192.168.30.153,dst=224.0.0.22,proto=2,tos=0xc0,ttl=1,frag=no) Apr 8 10:38:51 c83g155 ovs-vswitchd[4998]: ovs|00002|dpif_netdev(revalidator17)|ERR|internal error parsing flow key skb_priority(0),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(3),packet_type(ns=0,id=0),eth(src=00:11:22:33:44:00,dst=01:00:5e:00:00:16),eth_type(0x0800),ipv4(src=192.168.30.153,dst=224.0.0.22,proto=2,tos=0xc0,ttl=1,frag=no) Apr 8 10:39:08 c83g155 systemd[1919]: tracker-extract.service: Succeeded. Apr 8 10:41:52 c83g155 dbus-daemon[2076]: [session uid=0 pid=2076] Activating via systemd: service name='org.freedesktop.Tracker1.Miner.Extract' unit='tracker-extract.service' requested by ':1.72' (uid=0 pid=2706 comm="/usr/libexec/tracker-miner-fs ") Apr 8 10:41:52 c83g155 systemd[1919]: Starting Tracker metadata extractor... Apr 8 10:41:52 c83g155 kernel: mlx5_core 0000:07:01.2: mlx5_vdpa_set_status:1786:(pid 5370): performing device reset Apr 8 10:41:52 c83g155 kvm[5380]: 2 guests now active Apr 8 10:41:52 c83g155 dbus-daemon[2076]: [session uid=0 pid=2076] Successfully activated service 'org.freedesktop.Tracker1.Miner.Extract' Apr 8 10:41:52 c83g155 systemd[1919]: Started Tracker metadata extractor. Apr 8 10:42:16 c83g155 kernel: mlx5_core 0000:07:01.2: mlx5_vdpa_handle_set_map:473:(pid 5381): memory map update Apr 8 10:42:21 c83g155 ovs-vswitchd[4998]: ovs|00005|dpif_netdev(revalidator17)|ERR|internal error parsing flow key skb_priority(0),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(2),packet_type(ns=0,id=0),eth(src=00:11:22:33:44:10,dst=01:00:5e:00:00:16),eth_type(0x0800),ipv4(src=192.168.30.159,dst=224.0.0.22,proto=2,tos=0xc0,ttl=1,frag=no) Apr 8 10:42:21 c83g155 ovs-vswitchd[4998]: ovs|00006|dpif_netdev(revalidator17)|ERR|internal error parsing flow key skb_priority(0),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),recirc_id(0),dp_hash(0),in_port(4),packet_type(ns=0,id=0),eth(src=00:11:22:33:44:10,dst=01:00:5e:00:00:16),eth_type(0x0800),ipv4(src=192.168.30.159,dst=224.0.0.22,proto=2,tos=0xc0,ttl=1,frag=no) Apr 8 10:42:40 c83g155 systemd[1919]: tracker-extract.service: Succeeded.
ConsoleB
[root@c83g155 ~]# ovs-ofctl -O OpenFlow14 dump-ports br30-ovs OFPST_PORT reply (OF1.4) (xid=0x2): 3 ports port ens2f0: rx pkts=85847, bytes=8414161, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=85847, bytes=8414028, drop=0, errs=0, coll=? duration=423.079s rx rfc2819 broadcast_packets=2, tx rfc2819 multicast_packets=54, broadcast_packets=1, CUSTOM Statistics ovs_tx_failure_drops=0, ovs_tx_mtu_exceeded_drops=0, ovs_tx_qos_drops=0, ovs_rx_qos_drops=0, ovs_tx_invalid_hwol_drops=0, rx_missed_errors=0, rx_errors=0, tx_errors=0, rx_mbuf_allocation_errors=0, rx_q0_errors=0, rx_wqe_errors=0, rx_phy_crc_errors=0, rx_phy_in_range_len_errors=0, rx_phy_symbol_errors=0, tx_phy_errors=0, tx_pp_missed_interrupt_errors=0, tx_pp_rearm_queue_errors=0, tx_pp_clock_queue_errors=0, tx_pp_timestamp_past_errors=0, tx_pp_timestamp_future_errors=0, port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=55, errs=0, coll=0 duration=423.075s port "ens2f0_0": rx pkts=85847, bytes=8414028, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=85847, bytes=8414161, drop=0, errs=0, coll=? duration=422.848s CUSTOM Statistics ovs_tx_failure_drops=0, ovs_tx_mtu_exceeded_drops=0, ovs_tx_qos_drops=0, ovs_rx_qos_drops=0, ovs_tx_invalid_hwol_drops=0, rx_missed_errors=0, rx_errors=0, tx_errors=0, rx_mbuf_allocation_errors=0, rx_q0_errors=0, tx_pp_missed_interrupt_errors=0, tx_pp_rearm_queue_errors=0, tx_pp_clock_queue_errors=0, tx_pp_timestamp_past_errors=0, tx_pp_timestamp_future_errors=0,
ConsoleC
[root@c83g155 ~]# ovs-ofctl -O OpenFlow14 dump-ports br31-ovs OFPST_PORT reply (OF1.4) (xid=0x2): 3 ports port ens2f1: rx pkts=85847, bytes=8414104, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=85847, bytes=8414085, drop=0, errs=0, coll=? duration=450.620s rx rfc2819 broadcast_packets=2, tx rfc2819 multicast_packets=54, broadcast_packets=1, CUSTOM Statistics ovs_tx_failure_drops=0, ovs_tx_mtu_exceeded_drops=0, ovs_tx_qos_drops=0, ovs_rx_qos_drops=0, ovs_tx_invalid_hwol_drops=0, rx_missed_errors=0, rx_errors=0, tx_errors=0, rx_mbuf_allocation_errors=0, rx_q0_errors=0, rx_wqe_errors=0, rx_phy_crc_errors=0, rx_phy_in_range_len_errors=0, rx_phy_symbol_errors=0, tx_phy_errors=0, tx_pp_missed_interrupt_errors=0, tx_pp_rearm_queue_errors=0, tx_pp_clock_queue_errors=0, tx_pp_timestamp_past_errors=0, tx_pp_timestamp_future_errors=0, port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0 tx pkts=0, bytes=0, drop=55, errs=0, coll=0 duration=451.970s port "ens2f1_0": rx pkts=85847, bytes=8414085, drop=0, errs=0, frame=?, over=?, crc=? tx pkts=85847, bytes=8414104, drop=0, errs=0, coll=? duration=450.915s CUSTOM Statistics ovs_tx_failure_drops=0, ovs_tx_mtu_exceeded_drops=0, ovs_tx_qos_drops=0, ovs_rx_qos_drops=0, ovs_tx_invalid_hwol_drops=0, rx_missed_errors=0, rx_errors=0, tx_errors=0, rx_mbuf_allocation_errors=0, rx_q0_errors=0, tx_pp_missed_interrupt_errors=0, tx_pp_rearm_queue_errors=0, tx_pp_clock_queue_errors=0, tx_pp_timestamp_past_errors=0, tx_pp_timestamp_future_errors=0,
ConsoleD
[root@c77g153 ~]# ping 192.168.30.159 -f PING 192.168.30.159 (192.168.30.159) 56(84) bytes of data. --- 192.168.30.159 ping statistics --- 85742 packets transmitted, 85742 received, 0% packet loss, time 20040ms rtt min/avg/max/mdev = 0.093/0.111/7.100/0.055 ms, ipg/ewma 0.233/0.144 ms
<補足>
performing device reset | mlx5_coreによりmlx5_vdpaが初期化されています。 |
memory map update | mlx5_coreによりmlx5_vdpaのIOMMUメモリマッピングとアップデートが実行されています。なお、このログが出力されない限り、絶対に通信することはできないため、最重要メッセージとなります。 |
internal error parsing flow key | ovsがマルチキャスト関連のエラーを出していますが、特に問題はありません。気にしないでください。 |
ens2f0 "ens2f0_0" | 各ポートのtx/rxのパケットカウントとバイトカウントが上昇していることが確認できます。 |
以上です。
9.最後に
以下のサイトを参考にさせて頂きました。
https://www.redhat.com/en/blog?search=vdpa
https://docs.mellanox.com/pages/viewpage.action?pageId=43718786
https://community.mellanox.com/s/article/Basic-Debug-utilities-with-OVS-DPDK-offload-ASAP-Direct
https://static.sched.com/hosted_files/dpdkuserspace2020/ab/vDPA%20-%20DPDK%20Userspace%202020.pdf
https://netdevconf.info/1.2/slides/oct6/04_gerlitz_efraim_introduction_to_switchdev_sriov_offloads.pdf
https://www.mail-archive.com/dev@dpdk.org/msg175938.html
https://www.spinics.net/lists/netdev/msg693858.html
http://yunazuno.hatenablog.com/entry/2018/07/08/215118
https://ameblo.jp/makototgc/entry-12579674054.html
https://www.jianshu.com/p/091b60ea72dc
次回は、vDPA の設定方法 virtio_vdpa + VM編 を記載する予定です。
さらに、番外編として、NICの調達方法やovs-dpdk以外の設定方法、課題となっている事などを記載する予定です。
No | vm(qemu)/k8s | k8s Pod/VMI | vDPA Framework | vDPA Type | SR-IOV mode | Related Articles |
1 | vm | - | kernel | vhost | lagacy | Not started |
2 | vm | - | kernel | vhost | switchdev | vDPA の設定方法 vhost_vdpa + VM編 - Metonymical DeflectionThis article |
3 | vm | - | kernel | virtio | lagacy | Not started |
4 | vm | - | kernel | virtio | switchdev | Not started |
5 | vm | - | dpdk | vhost | lagacy | Not started |
6 | vm | - | dpdk | vhost | switchdev | Not started |
7 | vm | - | dpdk | virtio | lagacy | Not started |
8 | vm | - | dpdk | virtio | switchdev | vDPA の設定方法 virtio_vdpa + VM編 - Metonymical Deflection |
9 | k8s | pod | kernel | vhost | lagacy | vDPA の設定方法 vhost_vdpa + kubernetes編 - Metonymical Deflection |
10 | k8s | pod | kernel | vhost | switchdev | vDPA の設定方法 vhost_vdpa + kubernetes + Accelerated Bridge CNI編 - Metonymical Deflection |
11 | k8s | pod | kernel | virtio | lagacy | Not started |
12 | k8s | pod | kernel | virtio | switchdev | Not started |
13 | k8s | pod | dpdk | client | lagacy | Not started |
14 | k8s | pod | dpdk | client | switchdev | Not started |
15 | k8s | pod | dpdk | server | lagacy | Not started |
16 | k8s | pod | dpdk | server | switchdev | Not started |
*1:各種ドキュメントを確認した結果、vDPAの"v"は、virtual, vhost, virtioの3種類ありますが、意味は全て同じようです。本ブログでは、 Introduction to vDPA kernel framework に従い、virtioの表記で統一しました。
*2:対向機器に100Gbpsスイッチや100GNIC搭載サーバが用意できない場合を考慮し、ループ接続としています。但し、VMで生成したパケットが物理的に外部へ送信されることが重要と考えているため、fig.1の構成としています。
*3:私が理解した内容を記載しています。内容が誤っている場合には、ご指摘ください。
*4:MACアドレスの設定を実施しておかないと、VM起動後にVMがVFを認識しない事象を確認しました。
*5:coreやmodulesも同時にインストールされます
*6:蛇足ですが、bsf番号の前の「0000」は、Domain番号と呼ばれています。私が知る限りでは「0000」以外の値を見たことが無いため、あまり気にしなくてよいと思います。
*7:2-3.Mellanoxドライバ(OFED)のインストールで、インストール済みです。
*8:これはqemuのビルド時にspiceなどの関連パッケージをインストールしていないため、これらのデバイスを削除しないと仮想マシンが起動できませんでした。なお、vDPAとは直接関係がないため、これらの対処方法については割愛します。