Skip to content

vRAN trên VM

vRAN (virtualized RAN) chạy phần mềm của trạm gốc 5G (CU/DU, hay gNodeB) trên server x86 thông dụng thay cho thiết bị chuyên dụng. Phần đòi hỏi nhất là O-DU: xử lý PHY và MAC theo từng slot, trao đổi với O-RU qua fronthaul Ethernet, lại phải khớp thời gian với mạng qua PTP. Trang này nói về việc đặt O-DU vào VM. Kỹ thuật real-time dùng chung (pin vCPU, huge page, NUMA, đo cyclictest) nằm ở Real-time KVM tuning, nên làm trước.

Vì sao khó

  • Deadline cứng theo slot: với subcarrier spacing 30 kHz, một slot dài 0,5 ms gồm 14 symbol (khoảng 35,7 µs mỗi symbol). Gói fronthaul phải gửi và nhận đúng cửa sổ thời gian quanh symbol, trễ là mất dữ liệu radio.
  • Tải liên tục: PHY xử lý theo chu kỳ cố định, nên ngoài độ trễ trung bình còn phải kiểm soát đỉnh trễ.
  • Đồng bộ thời gian: toàn bộ chuỗi O-DU và O-RU phải chung một thang thời gian (PTP, thường kèm SyncE), nên nguồn thời gian của VM phải chính xác.

Mô hình tổng thể

O-RU ==(fronthaul: eCPRI qua Ethernet, PTP)== NIC (PF)
                                                 │ SR-IOV
                           ┌─────────────────────┼─────────────────────┐
                           VF0                   VF1                   VF2
                           │                     │
                  ┌────────┴────────┐   ┌────────┴────────┐
                  │ VM: O-DU        │   │ VM khác         │
                  │ DPDK (PMD iavf) │   │                 │
                  │ vCPU pin, 1G HP │   │                 │
                  └─────────────────┘   └─────────────────┘
        Host: PF driver, ptp4l/phc2sys, core housekeeping, KVM + VFIO + IOMMU
Lớp Công nghệ
Phần cứng NIC hỗ trợ SR-IOV và đồng hồ PTP phần cứng (PHC), tùy chọn thêm accelerator FEC/LDPC
Host KVM, VFIO, IOMMU, driver PF, ptp4l/phc2sys
Guest Kernel RT, DPDK, PMD của VF, stack O-DU

SR-IOV VF cho fronthaul

Fronthaul cần độ trễ thấp và gói đến đúng giờ, nên virtio (đi qua vhost, tiến trình hoặc kernel của host) thường không phù hợp: đường đi dài hơn, có thêm chuyển ngữ cảnh và nguồn jitter. Thay vào đó gán thẳng một VF của NIC vào VM bằng VFIO (I/O Virtualization), mỗi VM có một đường riêng tới phần cứng mà không cần card riêng cho từng VM. PF vẫn do host quản lý.

Điều kiện cần: IOMMU bật (intel_iommu=on iommu=pt trên kernel host, xem Memory Virtualization), BIOS bật SR-IOV và VT-d.

Tạo VF và cấu hình từ host (ví dụ card Intel E810, tên PF là ens1f0):

echo 4 > /sys/class/net/ens1f0/device/sriov_numvfs

# gán MAC, VLAN cho VF; cho phép guest dùng MAC khác nếu stack O-DU cần
ip link set ens1f0 vf 0 mac 00:11:22:33:44:66 vlan 564 spoofchk off trust on
ip link show ens1f0

# đưa VF cho VFIO
dpdk-devbind.py --status
dpdk-devbind.py -b vfio-pci 0000:3b:01.0

Với libvirt, VF được khai báo là thiết bị hostdev loại PCI (managed='yes'), với QEMU thì dùng -device vfio-pci,host=0000:3b:01.0.

Lưu ý khi chọn VF:

  • VF phải nằm cùng NUMA node với vCPU và RAM của VM (NUMA).
  • Cấu hình VLAN, MAC, QoS và giới hạn tốc độ của VF do PF áp, guest không tự đổi được. Nhờ đó cô lập tốt, nhưng cũng nghĩa là mọi thay đổi cần quyền ở host.
  • Số VF, tính năng (VLAN filtering, đồng bộ thời gian, ...) phụ thuộc NIC, firmware và driver. Kiểm tra theo tài liệu của nhà sản xuất NIC và ứng dụng O-DU đang dùng.
  • Accelerator FEC/LDPC cho PHY (ví dụ Intel ACC100) cũng thường gán vào VM theo cách tương tự (VF qua VFIO, dùng qua DPDK BBDev).
  • VM gán thiết bị passthrough không live migrate được.

DPDK trong guest

Stack O-DU gửi/nhận gói fronthaul bằng DPDK: poll mode driver (PMD) chạy ở userspace, đọc thẳng ring của NIC, không có ngắt và không qua kernel network stack. Trong guest, VF xuất hiện như một thiết bị PCI bình thường, dùng PMD iavf (với VF Intel). Xem thêm trang DPDK.

Hệ quả cho cấu hình:

  • Core dành riêng: PMD poll liên tục nên core chạy 100%. Dùng vCPU cô lập và pin (ở cả guest lẫn host), không dùng chung với tiến trình khác.
  • Huge page 1G: DPDK lấy bộ nhớ từ hugepage của guest, nên guest cần default_hugepagesz=1G hugepagesz=1G hugepages=N, và VM phải được backing bằng hugepage từ host (huge page).
  • IOMMU trong guest: để DPDK dùng vfio-pci trong guest cần IOMMU ảo (vIOMMU) hoặc chế độ no-IOMMU của VFIO. Bảo vệ DMA giữa VM và host đã do IOMMU của host đảm nhiệm, nên no-IOMMU trong guest chỉ bỏ cách ly giữa userspace và kernel của chính guest.
modprobe vfio enable_unsafe_noiommu_mode=1
modprobe vfio-pci
dpdk-devbind.py -b vfio-pci 0000:00:05.0
  • Kiểm tra nhanh khi mới dựng:
dpdk-testpmd -l 2-3 -a 0000:00:05.0 -- -i
testpmd> show port info 0
testpmd> show port stats all

-l chọn các core logical đã cô lập, -a cho phép đúng thiết bị cần dùng.

Khi đo độ trễ bằng cyclictest (Real-time KVM tuning), nên đo lúc PMD và stack O-DU đang chạy tải thật, vì tranh chấp cache và băng thông bộ nhớ chỉ lộ ra khi đó.

PTP qua VF

Đồng bộ thời gian là phần dễ sai nhất khi ảo hóa. Linux PTP đồng bộ đồng hồ phần cứng của NIC (PHC) nhờ timestamp ở tầng PHY/MAC, còn ứng dụng thì dùng đồng hồ hệ thống. Khi có VM, câu hỏi là ai chạy ptp4l, ai sở hữu PHC, và guest lấy giờ từ đâu.

Nhiều NIC giữ PHC ở PF, và VF không tự có PHC riêng hay hardware timestamp tương đương. Việc VF có timestamp phần cứng hay không phụ thuộc NIC, firmware và driver, nên kiểm tra trên đúng máy:

ethtool -T ens1f0          # trên host, PF: hardware-transmit/receive, PTP Hardware Clock
ethtool -T <if_vf>         # trong guest, nếu VF dùng driver kernel

Các mô hình thường gặp:

Mô hình Cách làm Ưu Nhược
A. PTP ở host, guest lấy giờ qua ptp_kvm ptp4l trên PF đồng bộ PHC với grandmaster, phc2sys đồng bộ CLOCK_REALTIME của host với PHC. Guest nạp ptp_kvm để lấy giờ từ host Đơn giản, nhiều VM dùng chung một nguồn giờ Độ chính xác trong guest bị giới hạn bởi hypercall và độ ổn định TSC của host, cần kiểm chứng
B. Gán nguyên PF (hoặc cổng) cho VM VM sở hữu NIC, chạy ptp4l với hardware timestamp như máy thật Chính xác như bare-metal, VM làm PTP master cho O-RU được Không chia sẻ NIC, mất lợi thế SR-IOV
C. Hybrid Cổng PTP riêng gán cho host (hoặc một VM), cổng fronthaul chia VF cho các VM Tách đường thời gian khỏi đường dữ liệu Cần nhiều cổng, cấu hình phức tạp hơn

Cách khai thác ptp_kvm ở mô hình A:

# host
ptp4l -i ens1f0 -m -f /etc/ptp4l.conf          # PHC của NIC <- grandmaster
phc2sys -s ens1f0 -c CLOCK_REALTIME -m -w      # CLOCK_REALTIME của host <- PHC

# guest
modprobe ptp_kvm                               # có thiết bị PTP "KVM virtual PTP", tên /dev/ptpN
chronyc sources -v                             # chrony với: refclock PHC /dev/ptp0 poll 2

Tùy cấu hình đồng bộ O-RAN mà O-DU làm master cho O-RU hay chỉ là slave của mạng (các cấu hình LLS-C1 đến C4 khác nhau ở chỗ này). Nếu O-DU phải là PTP master thì cần hardware timestamp trên cổng nối tới O-RU, nghĩa là mô hình B hoặc một ptp4l (boundary clock) chạy trên host.

Kiểm tra độ chính xác (cần đo ở đầu cuối nơi ứng dụng dùng giờ, không chỉ log của ptp4l):

ptp4l -m ...                  # theo dõi "rms" và "max" của offset
pmc -u -b 0 'GET TIME_STATUS_NP'   # trạng thái đồng bộ, offset từ master
phc_ctl /dev/ptp0 cmp         # so PHC với CLOCK_REALTIME

Cần đảm bảo invtsc cho guest, TSC ổn định và đồng bộ giữa các core, vì ptp_kvm và kvm-clock đều dựa vào đó.

Checklist triển khai

Bước Việc cần làm Xem
1. BIOS VT-x, VT-d, SR-IOV bật, C-state sâu tắt, SMT kiểm soát Real-time KVM tuning
2. Host isolcpus, nohz_full, rcu_nocbs, irqaffinity, huge page 1G Cấu hình host
3. NUMA NIC, accelerator, vCPU và RAM cùng node NUMA
4. VF Tạo VF, gán MAC/VLAN, bind vfio-pci SR-IOV VF
5. VM Pin vCPU và emulator, backing bằng hugepage, gán VF và accelerator Pin vCPU
6. Guest Cô lập vCPU, kernel RT, hugepage, DPDK, vIOMMU hoặc no-IOMMU DPDK trong guest
7. Thời gian ptp4l/phc2sys trên host, ptp_kvm hoặc PTP trong guest PTP qua VF
8. Kiểm chứng cyclictest có tải, testpmd, kiểm tra offset PTP, đếm gói mất/trễ fronthaul, chạy dài hạn Đo bằng cyclictest

Giới hạn và hướng mở rộng

  • Passthrough cho hiệu năng gần native nhưng đánh đổi tính linh hoạt: không migrate VM, VF và accelerator bị gắn với host.
  • Cô lập giữa nhiều VM cùng chia sẻ một server chỉ tốt khi tài nguyên được chia tĩnh. Cache L3, băng thông bộ nhớ và PCIe vẫn là tài nguyên dùng chung và có thể gây nhiễu, cần đo với tải thật.
  • Chạy O-DU dưới dạng container trên Kubernetes cũng phổ biến (CPU Manager static, Topology Manager, SR-IOV device plugin, hugepage làm resource), chung các nguyên tắc ở trên. Phần container có thể bổ sung thành trang riêng trong nhóm này.
  • Nếu yêu cầu vượt khả năng của KVM trên server tổng quát, xem Partitioning hypervisor.

Đọc thêm