1. Tổng quan.
F-Stack kết hợp với Nginx để cung cấp một framework với network hiệu suất cao, sử dụng DPDK để thay thế hoặc tối ưu hóa của kernel truyền thống.
Dưới đây là sơ đồ thể hiện cách F-Stack hoạt động với Nginx:
+--------+
+------------------------+ |
channel: socketpair |
+------------------------+ | signal(reload, quit..)
|
|
+---------v--------+
| |
+----------------+ master process +---------------+
| | | |
| channel +----------+-------+ |
| | channel |
| channel | |
| | |
+---------+----------+ +----------+--------+ +---------+--------+
first one to start | | | | | |
last one to exit<-+ primary worker | | secondary worker | | secondary worker |
| | | | | |
+--------------------+ +-------------------+ +------------------+
+--------------------+ +-------------------+
| | | |
| fstack,kernel | | fstack,kernel |
| and channel | | and channel |
| loop thread | | loop thread |
| | | |
+--------------------+ +-------------------+
woker process cycle woker process cycle
Cấu trúc cơ bản của Nginx khi dùng F-Stack
- Master Process (Quản lý chính):
- Quản lý các worker processes (tiến trình làm việc).
- Nhận tín hiệu từ hệ thống (ví dụ: reload, quit hoặc các tín hiệu khác).
- Sử dụng cơ chế socketpair để giao tiếp với các worker.
- Primary Worker:
- Tiến trình worker chính, được tạo ra đầu tiên bởi master process.
- Thiết lập các cấu hình F-Stack.
- Quản lý luồng dữ liệu mạng qua F-Stack hoặc kernel.
- Secondary Workers:
- Các worker khác hỗ trợ xử lý yêu cầu HTTP.
- Kết nối với Primary Worker thông qua các kênh giao tiếp.
Quy trình hoạt động của F-Stack với Nginx
- Khởi động Master Process:
- Master Process bắt đầu và tạo Primary Worker.
- Duy trì giao tiếp với các worker thông qua socketpair.
- Khởi tạo F-Stack trong Primary Worker:
- Gọi hàm
ff_init()
để khởi động F-Stack. - Thiết lập cơ sở hạ tầng mạng dựa trên DPDK.
- Gọi hàm
- Chạy Vòng Lặp Xử Lý Sự Kiện:
- Gọi
ff_run(worker_process_cycle)
để bắt đầu vòng lặp sự kiện. - Xử lý:
- Channel Events: Trao đổi thông tin giữa các worker (qua các kênh nội bộ).
- Host Events: Xử lý yêu cầu HTTP từ ứng dụng web.
- F-Stack Events: Quản lý giao tiếp mạng qua DPDK.
- Gọi
- Tạo Secondary Workers:
- Sau khi Primary Worker khởi động thành công, Master Process tiếp tục tạo các Secondary Worker.
- Các Secondary Worker chia sẻ tài nguyên mạng do F-Stack quản lý và thực hiện xử lý song song.
- Quản lý Kênh (Channel Management):
- Sử dụng các channel để truyền tải dữ liệu giữa Master Process, Primary Worker và Secondary Workers.
F-Stack có thể kết hợp với Nginx để cung cấp một framework mạng hiệu suất cao, sử dụng DPDK để thay thế hoặc tối ưu hóa của kernel truyền thống. Sơ đồ dưới đây cung cấp cách F-Stack hoạt động với Nginx:
Cấu trúc cơ bản của Nginx khi dùng F-Stack.
- Master Process (Quản lý chính):
- Quản lý các worker processes (tiến trình làm việc).
- Nhận tín hiệu từ hệ thống (ví dụ: reload, quit, hoặc các tín hiệu khác).
- Sử dụng cơ chế socketpair để giao tiếp với các worker.
- Primary Worker:
- Tiến trình worker chính, được tạo ra đầu tiên bởi master process.
- Thiết lập các cấu hình F-Stack.
- Quản lý luồng dữ liệu mạng qua F-Stack hoặc kernel.
- Secondary Workers:
- Các worker khác hỗ trợ xử lý yêu cầu HTTP.
- Kết nối với Primary Worker thông qua các kênh giao tiếp.
Quy trình hoạt động của F-Stack với Nginx
- Khởi động Master Process:
- Master Process bắt đầu và tạo Primary Worker.
- Duy trì giao tiếp với các worker thông qua socketpair.
- Khởi tạo F-Stack trong Primary Worker:
- Gọi hàm
ff_init()
để khởi động F-Stack. - Thiết lập cơ sở hạ tầng mạng dựa trên DPDK.
- Gọi hàm
- Chạy Vòng Lặp Xử Lý Sự Kiện:
- Gọi
ff_run(worker_process_cycle)
để bắt đầu vòng lặp sự kiện. - Xử lý:
- Channel Events: Trao đổi thông tin giữa các worker (qua các kênh nội bộ).
- Host Events: Xử lý yêu cầu HTTP từ ứng dụng web.
- F-Stack Events: Quản lý giao tiếp mạng qua DPDK.
- Gọi
- Tạo Secondary Workers:
- Sau khi Primary Worker khởi động thành công, Master Process tiếp tục tạo các Secondary Worker.
- Các Secondary Worker chia sẻ tài nguyên mạng do F-Stack quản lý và thực hiện xử lý song song.
- Quản lý Kênh (Channel Management):
- Sử dụng các channel để truyền tải dữ liệu giữa Master Process, Primary Worker và Secondary Workers.
Sự khác biệt chính khi sử dụng F-Stack
Các chỉ thị mới (Directives):
kernel_network_stack
:on
: Sử dụng kernel.off
: Sử dụng F-Stack.- Cấu hình này quyết định liệu server sẽ chạy trên F-Stack hay kernel.
proxy_kernel_network_stack
:- Tương tự
kernel_network_stack
, nhưng áp dụng cho các kết nối proxy.
- Tương tự
schedule_timeout
:- Thời gian chờ giữa các lần polling của kernel. Mặc định là 30ms.
Điểm khác biệt:
- Hiệu năng cao hơn: F-Stack sử dụng DPDK để xử lý các gói mạng trực tiếp trên user space, giảm thiểu độ trễ và chi phí quản lý của kernel.
- Chuyển đổi linh hoạt: Có thể cấu hình từng server hoặc proxy để sử dụng F-Stack hoặc kernel tùy trường hợp.
Tóm tắt quy trình:
- Master Process khởi động và tạo Primary Worker.
- Primary Worker khởi tạo F-Stack và vòng lặp xử lý sự kiện mạng.
- Các Secondary Workers được tạo để xử lý song song các yêu cầu HTTP.
- F-Stack xử lý các giao tiếp ở user space, giảm tải cho kernel và tăng hiệu năng.
2.1 Update gói.
apt update
2.2 Tải source code về máy.
mkdir -p /data/f-stack
git clone https://github.com/F-Stack/f-stack.git /data/f-stack
2.3. Cài đặt các gói phụ thuộc.
Cài đặt một số gói phần mềm cần thiết để xây dựng và chạy các ứng dụng, đặc biệt là các ứng dụng yêu cầu biên dịch, các gói support network và cấu hình hệ thống.
apt-get install git gcc openssl libssl-dev linux-headers-$(uname -r) bc libnuma1 libnuma-dev libpcre3 libpcre3-dev zlib1g-dev meson python3-pip -y
- git: Dùng để quản lý mã nguồn (version control), clone và tải về mã nguồn từ các kho lưu trữ như GitHub.
- python: Ngôn ngữ lập trình Python.
- gcc: GNU Compiler Collection, trình biên dịch dùng để biên dịch mã nguồn C/C++.
- openssl: Cung cấp thư viện hỗ trợ mã hóa, chứng chỉ SSL/TLS và các thao tác bảo mật liên quan
- libssl-dev: Thư viện phát triển OpenSSL, cung cấp các công cụ cần thiết để xây dựng các ứng dụng sử dụng SSL/TLS.
- linux-headers-$(uname -r): Cài đặt các file kernel tương ứng với phiên bản kernel hiện tại (
$(uname -r)
), cần thiết khi biên dịch các module kernel hoặc phần mềm phụ thuộc kernel. - bc: Công cụ dòng lệnh để thực hiện các phép toán số học chính xác (arbitrary precision). Thường được dùng trong các lệnh shell liên quan đến cấu hình hệ thống.
- libnuma1: Thư viện hỗ trợ quản lý tài nguyên bộ nhớ không đồng nhất (NUMA – Non-Uniform Memory Access).
- libnuma-dev: Gói phát triển của
libnuma1
, cung cấp các files cần thiết để xây dựng ứng dụng sử dụng NUMA. - libpcre3: Thư viện thực thi các biểu thức chính quy (Regular Expressions). Thường được sử dụng bởi các ứng dụng như Nginx hoặc grep.
libpcre3-dev
: Phiên bản phát triển củalibpcre3
, cung cấp các công cụ để xây dựng ứng dụng sử dụng biểu thức chính quy.- zlib1g-dev: Thư viện phát triển cho nén và giải nén dữ liệu, sử dụng định dạng zlib/gzip.
- meson: Công cụ thường dùng để cấu hình và biên dịch mã nguồn (thay thế cho
make
). - python3-pip: Trình quản lý gói cho Python 3, dùng để cài đặt các thư viện Python
2.4. Cài đặt thư viện pyelftools
.
Cài đặt thư viện pyelftools
, một thư viện Python cho phép bạn phân tích các file ELF (Executable and Linkable Format). ELF là định dạng file được sử dụng chủ yếu trong các hệ thống Linux và Unix-like để lưu trữ các chương trình nhị phân, các thư viện.
pip3 install pyelftools
2.5. Chỉnh sử igb_uio.c
.
Nếu bạn đang làm lab trên máy ảo, bạn nên thực hiện chỉnh sửa dưới đây để đảm bảo driver igb_uio hoạt động chính xác. Điều này giúp tránh lỗi khi driver kiểm tra khả năng hỗ trợ INTx masking trên thiết bị PCI trong môi trường ảo hóa.
Chỉnh sửa file: Mở file igb_uio.c
vi /data/f-stack/dpdk/kernel/linux/igb_uio/igb_uio.c
Tìm dòng: Tìm đến dòng 274 hoặc đoạn code chứa:
if (pci_intx_mask_supported(udev->pdev)) {
Thay đổi thành:
if (true || pci_intx_mask_supported(udev->pdev)) {
2.6. Compile DPDK.
Biên dịch driver igb_uio bằng các command sau.
cd /data/f-stack/dpdk
meson -Denable_kmods=true -Ddisable_libs=flow_classify build
ninja -C build
ninja -C build install
Nếu sau khi build xong mà bạn cần thay đổi nội dung files /data/f-stack/dpdk/kernel/linux/igb_uio/igb_uio.c
thì sau khi chỉnh sửa, bạn cần chạy lệnh ninja -C build clean
để clean và biên dịch lại DPDK.
Ví dụ:
cd /data/f-stack/dpdk
meson -Denable_kmods=true -Ddisable_libs=flow_classify build
ninja -C build clean
ninja -C build
ninja -C build install
2.7. Cấp phát một số lượng hugepages.
Sử dụng lệnh echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
để cấu hình hệ thống Linux để yêu cầu kernel cấp phát một số lượng hugepages nhất định. Dưới đây là chi tiết về các phần của lệnh và mục đích sử dụng. Trong trường hợp này, mỗi hugepage có kích thước 2048 kB (2 MB). Linux hỗ trợ các loại hugepages với các kích thước khác nhau (ví dụ: 2MB, 1GB, v.v.).
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
Mục đích của việc sử dụng hugepages:
- Tăng hiệu suất bộ nhớ: Hugepages giúp giảm các hành động mà hệ điều hành phải thực hiện để quản lý bộ nhớ trong hệ thống vì chúng sử dụng các slot bộ nhớ lớn hơn (thường là 2 MB hoặc 1 GB thay vì 4 KB). Điều này giúp giảm số lượng bộ nhớ mà hệ điều hành cần theo dõi, từ đó giảm thiểu overhead của hệ thống khi quản lý bộ nhớ.
- Ví dụ:
- Sử dụng mỗi slot bộ nhớ có size là 4KB: Bộ nhớ 1GB sẽ được chia thành 256,000 slot loại 4KB. Mỗi lần bạn cần ánh xạ bộ nhớ hoặc thực hiện thao tác quản lý slot, hệ điều hành sẽ cần thực hiện thao tác cho mỗi slot 4KB, tạo ra overhead.
- Sử dụng mỗi slot bộ nhớ có size là 1GB: Với hugepages, bạn chỉ cần theo dõi 1 slot có bộ nhớ 1GB. Điều này giảm bớt thao tác và tài nguyên cần thiết để quản lý bộ nhớ, làm cho hệ thống hoạt động nhanh hơn và ít tiêu tốn tài nguyên hơn.
- Ví dụ:
- Hiệu suất cao trong các ứng dụng yêu cầu bộ nhớ lớn: Các ứng dụng như cơ sở dữ liệu, máy ảo, và các ứng dụng khoa học tính toán thường yêu cầu một lượng lớn bộ nhớ. Sử dụng hugepages giúp giảm sự phân mảnh bộ nhớ và có thể cải thiện hiệu suất của các ứng dụng này.
- Giảm TLB (Translation Lookaside Buffer) misses: Việc sử dụng hugepages giúp giảm số lần truy cập TLB, vì mỗi bộ nhớ lớn hơn giúp giữ nhiều dữ liệu hơn trong bộ đệm TLB, từ đó cải thiện tốc độ truy cập bộ nhớ.
Khi nào sử dụng:
- Nếu bạn đang chạy các ứng dụng cần tối ưu hóa hiệu suất bộ nhớ, chẳng hạn như database hoặc virtual machines (ví dụ: KVM), việc sử dụng hugepages có thể mang lại lợi ích lớn.
- Đối với các ứng dụng có bộ nhớ sử dụng liên tục và kích thước bộ nhớ lớn, sử dụng hugepages giúp giảm thiểu overhead quản lý bộ nhớ.
Lưu ý:
- Việc sử dụng hugepages yêu cầu cấp phát bộ nhớ ở mức hệ thống và bạn cần đảm bảo rằng hệ thống của bạn có đủ bộ nhớ khả dụng cho các hugepages. Số lượng hugepages được cấp phát phải được tính toán sao cho phù hợp với yêu cầu của ứng dụng.
- Khi bạn chạy lệnh trên, hệ thống sẽ cấp phát 1024 hugepages, mỗi page có kích thước 2MB, tương đương với tổng số bộ nhớ là:
1024 * 2MB = 2048 MB = 2 GB
Điều này có nghĩa là hệ thống sẽ cấp phát 2GB bộ nhớ dưới dạng hugepages có kích thước 2MB mỗi slot.
2.8. Mount một filesystem hugetlbfs vào thư mục /mnt/huge
(hệ thống filesystem được sử dụng để hỗ trợ việc sử dụng hugepages).
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
cat >> /etc/fstab << 'OEF'
nodev /mnt/huge hugetlbfs defaults 0 0
OEF
mount -a
Hugetlbfs là hệ thống filesystem đặc biệt được sử dụng để hỗ trợ việc sử dụng hugepages trong hệ thống. Để có thể sử dụng hugepages, hệ điều hành cần một cách để truy cập và quản lý chúng thông qua hệ thống filesystem hugetlbfs
.Việc mount hugetlbfs
vào /mnt/huge
giúp các ứng dụng có thể truy cập và sử dụng các hugepages đã được phân bổ trong hệ thống.
Lưu ý nodev
là tham số chỉ ra rằng không có thiết bị vật lý cụ thể gắn liền với hệ thống filesystem này. hugetlbfs
không yêu cầu thiết bị vật lý mà chỉ sử dụng bộ nhớ hệ thống.
Để kiểm tra xem bạn đã mount thành công hugetlbfs
vào thư mục /mnt/huge
, bạn có thể sử dụng các lệnh sau:
Lệnh mount
sẽ hiển thị tất cả các hệ thống tệp đang được mount trên hệ thống. Bạn có thể lọc kết quả để kiểm tra xem hugetlbfs
có được mount hay không:
shell> mount | grep hugetlbfs
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
nodev on /mnt/huge type hugetlbfs (rw,relatime,pagesize=2M)
Lệnh này sẽ hiển thị danh sách các điểm mount hiện tại:
shell> cat /proc/mounts | grep hugetlbfs
hugetlbfs /dev/hugepages hugetlbfs rw,relatime,pagesize=2M 0 0
nodev /mnt/huge hugetlbfs rw,relatime,pagesize=2M 0 0
- Bạn sẽ thấy có 2 kết quả được trả về như sau:
- Kết quả 1 cho thấy
hugetlbfs
đã được mount vào thư mục/dev/hugepages
với kích thước slot bộ nhớ là2M
. Đây là nơi DPDK sẽ sử dụng để truy cập bộ nhớ lớn (hugepages
). - Kết quả 2 cho thấy
hugetlbfs
cũng đã được mount vào thư mục/mnt/huge
. Điều này có nghĩa là bạn đã cấu hình thêm một điểm mount nữa chohugetlbfs
và nó đang sử dụng slot bộ nhớ có kích thước2M
.
- Kết quả 1 cho thấy
2.9. Chuyển card mạng sang chế độ được quản lý bởi DPDK.
Quy trình này thực hiện các bước cấu hình để chuyển một card mạng (NIC) sang chế độ được quản lý bởi DPDK (Data Plane Development Kit) bằng cách sử dụng driver igb_uio
. Đây là bước cần thiết để offload việc xử lý gói tin sang DPDK, nhằm tăng hiệu suất xử lý mạng.
Load các module cần thiết.
modprobe uio
insmod /data/f-stack/dpdk/build/kernel/linux/igb_uio/igb_uio.ko
insmod /data/f-stack/dpdk/build/kernel/linux/kni/rte_kni.ko carrier=on
modprobe uio
:- Nạp module UIO (User-space I/O) vào kernel. Module này cho phép các ứng dụng được quản lý bởi user space giao tiếp với thiết bị phần cứng trực tiếp.
insmod igb_uio.ko
:- Nạp module
igb_uio
, một driver DPDK UIO đặc biệt, giúp quản lý NIC trong các ứng dụng được quản lý bởi user space. - Driver này thay thế driver kernel mặc định (như
e1000
hoặcvmxnet3
) để NIC được quản lý bởi DPDK.
- Nạp module
insmod rte_kni.ko carrier=on
:- Nạp module KNI (Kernel NIC Interface) để tạo kết nối giữa kernel và DPDK.
- Khi DPDK (Data Plane Development Kit) hoạt động với các driver như
igb_uio
vàvfio-pci
, nó giúp bypass (bỏ qua) kernel network stack để xử lý các gói tin trực tiếp trong user space, tăng tốc độ xử lý mạng. - Tuy nhiên, KNI (Kernel NIC Interface) là một ngoại lệ. KNI được sử dụng để kết nối lại DPDK với kernel khi cần thiết. Cụ thể, mặc dù DPDK có thể điều khiển NIC trực tiếp mà không cần kernel, KNI cho phép kernel và DPDK giao tiếp với nhau khi cần. Điều này có nghĩa là DPDK vẫn có thể xử lý gói tin ở không gian user space, nhưng nếu có tình huống cần giao tiếp với kernel (như khi cần sử dụng các tiện ích mạng của hệ điều hành hoặc truy cập các giao thức mạng của kernel), KNI cung cấp cầu nối để làm điều đó.
- Vậy, mặc dù DPDK giúp giảm tải cho kernel bằng cách trực tiếp quản lý các NIC và gói tin ở user space, KNI cho phép DPDK và kernel phối hợp với nhau khi cần thiết. KNI chủ yếu được dùng trong các tình huống như khi muốn sử dụng các công cụ mạng trong kernel, nhưng vẫn muốn tối ưu hiệu suất của DPDK trong phần lớn thời gian.
- Khi DPDK (Data Plane Development Kit) hoạt động với các driver như
- Tham số
carrier=on
đảm bảo trạng thái kết nối mạng được báo cáo là “UP” ngay cả khi NIC được điều khiển bởi DPDK.
- Nạp module KNI (Kernel NIC Interface) để tạo kết nối giữa kernel và DPDK.
Kiểm tra trạng thái card mạng.
Sử dụng lệnh ip a để kiểm tra trạng thái card mạng trước khi thay đổi để xem sự khác nhau giữ trước và sau khi thay đổi. Mình sử dụng card mạng ens192 để chuyển nó sang quản lý bởi DPDK.
shell> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:80:d0:38 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.237.7.78/24 brd 10.237.7.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe80:d038/64 scope link
valid_lft forever preferred_lft forever
3: ens192: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 00:50:56:80:28:3c brd ff:ff:ff:ff:ff:ff
altname enp11s0
Sử dụng lệnh python3 dpdk-devbind.py –status để kiểm tra trạng thái card mạng để hiển thị danh sách các thiết bị mạng cùng trạng thái driver hiện tại và giúp xác định NIC nào đang sử dụng driver kernel (vmxnet3
, e1000
) hoặc driver DPDK (igb_uio
).
Di chuyển vào thư mục /data/f-stack/dpdk/usertools
.
cd /data/f-stack/dpdk/usertools
Hãy thử check status trước bằng lệnh python3 dpdk-devbind.py –status để thấy sự thay đổi trước và sau khi thay đổi drive.
shell> python3 dpdk-devbind.py --status
Network devices using kernel driver
===================================
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens160 drv=vmxnet3 unused=igb_uio,vfio-pci *Active*
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens192 drv=vmxnet3 unused=igb_uio,vfio-pci
No 'Baseband' devices detected
==============================
No 'Crypto' devices detected
============================
No 'DMA' devices detected
=========================
No 'Eventdev' devices detected
==============================
No 'Mempool' devices detected
=============================
No 'Compress' devices detected
==============================
No 'Misc (rawdev)' devices detected
===================================
No 'Regex' devices detected
===========================
Ngắt card mạng khỏi kernel là bước cần thiết để ngăn kernel chiếm quyền quản lý NIC khi thay đổi driver.
ifconfig ens192 down
Gắn driver igb_uio
cho NIC.
python3 dpdk-devbind.py --bind=igb_uio ens192
- Chuyển NIC
ens192
từ driver kernel mặc định (nhưvmxnet3
) sang driver DPDK (igb_uio
). - Sau khi thực hiện lệnh này, NIC sẽ không còn xuất hiện trong danh sách
ifconfig
hoặcip a
, vì nó không được quản lý bởi kernel nữa.
Kiểm tra lại trạng thái NIC bằng lệnh python3 dpdk-devbind.py --status
để xem sự khác biệt trước và sau khi chuyển đổi quản lý từ kernel sang DPDK.
shell> python3 dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' drv=igb_uio unused=vmxnet3,vfio-pci
Network devices using kernel driver
===================================
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens160 drv=vmxnet3 unused=igb_uio,vfio-pci *Active*
No 'Baseband' devices detected
==============================
No 'Crypto' devices detected
============================
No 'DMA' devices detected
=========================
No 'Eventdev' devices detected
==============================
No 'Mempool' devices detected
=============================
No 'Compress' devices detected
==============================
No 'Misc (rawdev)' devices detected
===================================
No 'Regex' devices detected
===========================
Kết quả trước và sau khi thay đổi card mạng cho thấy chúng ta đã thay đổi driver của card mạng ens192
từ driver kernel mặc định vmxnet3
sang driver DPDK tương thích igb_uio
.
Trước khi thay đổi (sử dụng driver kernel vmxnet3
):
Network devices using kernel driver
===================================
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens160 drv=vmxnet3 unused=igb_uio,vfio-pci *Active*
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens192 drv=vmxnet3 unused=igb_uio,vfio-pci
- ens160 sử dụng driver
vmxnet3
và thiết bị này đang hoạt động (dấu*Active*
). - ens192 cũng sử dụng driver
vmxnet3
, nhưng không có thiết bị nào sử dụngigb_uio
hayvfio-pci
ở thời điểm này, tức là nó vẫn đang dùng driver kernelvmxnet3
.
Sau khi thay đổi (chuyển sang DPDK driver igb_uio
):
Network devices using DPDK-compatible driver
============================================
0000:0b:00.0 'VMXNET3 Ethernet Controller 07b0' drv=igb_uio unused=vmxnet3,vfio-pci
- ens192 bây giờ đã chuyển sang sử dụng driver
igb_uio
, một driver DPDK tương thích, thay vìvmxnet3
như trước. Điều này có nghĩa là card mạng này sẽ được DPDK xử lý thay vì kernel driver. - Trên dòng này, bạn có thể thấy rằng card mạng
ens192
đang sử dụng driverigb_uio
và không còn sử dụng driver kernelvmxnet3
nữa.
Xem kết quả dưới thì ens160 vẫn sử dụng driver kernel vmxnet3
, và nó vẫn hoạt động bình thường như trước.
0000:03:00.0 'VMXNET3 Ethernet Controller 07b0' if=ens160 drv=vmxnet3 unused=igb_uio,vfio-pci Active
2.10. Cài đặt pkg-config.
F-Stack yêu cầu phiên bản pkg-config từ 0.28 trở lên để đảm bảo nó hỗ trợ các tính năng cần thiết cho việc cấu hình và biên dịch DPDK, cũng như các thành phần liên quan.
Trong trường hợp nếu hệ thống đang sử dụng một phiên bản cũ hơn của pkg-config (ví dụ như dưới 0.28), thì việc nâng cấp lên phiên bản mới hơn là cần thiết. Các bước được cung cấp để nâng cấp pkg-config là chính xác.
Đầu tiên hãy sao lưu phiên bản cũ của pkg-config
.
mv /usr/bin/pkg-config /usr/bin/pkg-config.bak
Chạy các lệnh sau để nâng cấp:
cd /data
wget https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz
tar xzvf pkg-config-0.29.2.tar.gz
cd pkg-config-0.29.2
./configure --with-internal-glib
make
make install
ln -s /usr/local/bin/pkg-config /usr/bin/pkg-config
Trường hợp của mình chưa cài nó nên mình sẽ cài mới bằng lệnh apt cho nhanh do hiện tại bản mới nhất cũng là 0.29.2 khi cài đặt bằng apt.
shell> pkg-config --version
Command 'pkg-config' not found, but can be installed with:
Cú pháp cài đặt pkg-config như dưới.
apt install pkg-config -y
Xác minh đúng phiên bản của pkg-config.
shell> pkg-config --version
0.29.2
2.10. Khởi tạo thư viện F-Stack và các file thực thi (binaries) cần thiết để sử dụng cho F-Stack.
Gán biến môi trường.
export FF_PATH=/data/f-stack
export PKG_CONFIG_PATH=/usr/local/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
Nhớ đảm bảo trong thư mục /usr/local/lib/x86_64-linux-gnu/pkgconfig
có chứa file libdpdk.pc
nhé.
shell> ls /usr/local/lib/x86_64-linux-gnu/pkgconfig
libdpdk-libs.pc libdpdk.pc
Kiểm tra liệu pkg-config
đã nhận diện được DPDK hay chưa.
shell> pkg-config --modversion libdpdk
22.11.6
Vì mỗi phiên bản hoặc mỗi OS có thể các file .pc sẽ được lưu ở một vị trí khác nhau. Nếu bạn không biết nó nằm chính xác ở đâu bạn hãy xử lý bằng cách sau.
Bạn cần đảm bảo rằng DPDK đã cài đặt các file .pc
. Chạy lệnh find /usr -type f -name ‘*.pc’ hoặc find /usr/local -type f -name ‘*.pc’ để tìm kiếm file .pc
.
Sử dụng lệnh find /usr -type f -name ‘*.pc’.
shell> find /usr -type f -name '*.pc'
/usr/share/pkgconfig/xkeyboard-config.pc
/usr/share/pkgconfig/udev.pc
/usr/share/pkgconfig/systemd.pc
/usr/share/pkgconfig/shared-mime-info.pc
/usr/share/pkgconfig/iso-codes.pc
/usr/share/pkgconfig/bash-completion.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/python-3.10-embed.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/zlib.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libpcre.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/expat.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libcrypto.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libpcrecpp.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/numa.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libxcrypt.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/openssl.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libssl.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libpcre32.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libpcreposix.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libnsl.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/python-3.10.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libtirpc.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/libpcre16.pc
/usr/lib/pkgconfig/libdmmp.pc
/usr/local/lib/x86_64-linux-gnu/pkgconfig/libdpdk.pc
/usr/local/lib/x86_64-linux-gnu/pkgconfig/libdpdk-libs.pc
Hoặc lệnh find /usr/local -type f -name ‘*.pc.
shell> find /usr/local -type f -name '*.pc'
/usr/local/lib/x86_64-linux-gnu/pkgconfig/libdpdk.pc
/usr/local/lib/x86_64-linux-gnu/pkgconfig/libdpdk-libs.pc
Kiểm tra xem có file nào liên quan đến DPDK hoặc F-Stack (ví dụ: libdpdk.pc
) không. Nếu không, bạn có thể cần cài đặt lại hoặc cấu hình DPDK đúng cách để tạo file .pc
.
Đường dẫn thay thế cho PKG_CONFIG_PATH:
Nếu bạn tìm thấy các file .pc
, thêm các đường dẫn chứa chúng vào PKG_CONFIG_PATH. Ví dụ:
export PKG_CONFIG_PATH=/usr/local/lib/x86_64-linux-gnu/pkgconfig/:/usr/local/lib/pkgconfig:/usr/share/pkgconfig
2.11. Build và cài đặt thư viện F-Stack vào hệ thống.
Bước này build và cài đặt thư viện cốt lõi của F-Stack. Đây là một bước quan trọng trong quá trình thiết lập F-Stack, hãy di chuyển vào folder /data/f-stack/lib, sau đó make và mak install nó.
cd /data/f-stack/lib
make
make install
2.12. Cài đặt Gawk.
Gói gawk
được cài để thay thế mawk nhằm đảm bảo tính tương thích và hoạt động đầy đủ của các tập lệnh hoặc công cụ liên quan đến F-Stack.
apt-get install gawk -y
Xác minh việc cài đặt gawk thành công.
shell> gawk --version
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1)
Copyright (C) 1989, 1991-2020 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
2.12. Cài đặt Nginx.
Để chạy được Nginx với F-Stack thì bạn cần sử dụng gói cài đặt Nginx phiên bản 1.25.2 đi kèm với F-Stack nhé. Dưới đây là quy trình cài đặt Nginx.
cd /data/f-stack/app/nginx-1.25.2
bash ./configure --prefix=/usr/local/nginx_fstack --with-ff_module
make
make install
Hãy chỉnh sửa file /usr/local/nginx_fstack/conf/nginx.conf
với các tham số sau (dưới đây là tham số do tác giả cung cấp, tùy vào mỗi hệ thống mà bạn có thể thay đổi tham số cho phù hợp nhé).
Nếu bạn không tìm thấy file nginx.conf trên hệ thống của mình, có thể dùng lệnh find /usr/local/nginx_fstack -name "nginx.conf
” để tìm kiếm thử nhé. Hoặc hãy để ý khi bạn chạy xong command bash ./configure --prefix=/usr/local/nginx_fstack --with-ff_module
, bạn cũng sẽ thất output dạng vây. Nó liệt kê chi tiết các file mà bạn có thể dùng tới nó.
creating objs/Makefile
FF_PATH environment variable not defined, default FF_PATH=/usr/local
Configuration summary
+ using system PCRE library
+ OpenSSL library is not used
+ using system zlib library
nginx path prefix: "/usr/local/nginx_fstack"
nginx binary file: "/usr/local/nginx_fstack/sbin/nginx"
nginx modules path: "/usr/local/nginx_fstack/modules"
nginx configuration prefix: "/usr/local/nginx_fstack/conf"
nginx configuration file: "/usr/local/nginx_fstack/conf/nginx.conf"
nginx pid file: "/usr/local/nginx_fstack/logs/nginx.pid"
nginx error log file: "/usr/local/nginx_fstack/logs/error.log"
nginx http access log file: "/usr/local/nginx_fstack/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
Theo hướng dẫn từ F-Stack Nginx APP Guide, bạn cần thực hiện các thay đổi sau trong file /usr/local/nginx_fstack/conf/nginx.conf
như sau.
Chạy dưới tài khoản root
:
user root; # root account is necessary
Thêm đường dẫn đến file cấu hình f-stack.conf
ví dụ như dưới.
fstack_conf /usr/local/nginx_fstack/conf/f-stack.conf;
Đảm bảo worker_processes
trong nginx.conf
khớp với số lượng lõi CPU được chỉ định trong dpdk.lcore_mask
(trong f-stack.conf
):
worker_processes 1; # ví dụ nếu dpdk.lcore_mask = 0x1
Tăng giới hạn kết nối.
events {
worker_connections 102400; # tăng giới hạn kết nối
use kqueue; # sử dụng kqueue
}
Vô hiệu hóa sendfile
:
sendfile off; # cần tắt sendfile
File /usr/local/nginx_fstack/conf/f-stack.conf
này chứa cấu hình F-Stack như dpdk.lcore_mask
, dpdk.port_list
và các thiết lập khác. Đảm bảo rằng bạn đã thiết lập nó phù hợp với hệ thống của mình.
Ví dụ dưới đây mình sẽ đặt IP cho card mạng này phục vụ cho việc truy cập webserver vào Nginx.
[port0]
addr=10.237.7.79
netmask=255.255.255.0
broadcast=10.237.7.255
gateway=10.237.7.1
3. Kiểm tra kết quả.
Đầu tiên bạn có thể check trước IP 10.237.7.79 hiện tại chưa có kết nối bằng lệnh ICMP.
shell> ping -c 4 10.237.7.79
PING 10.237.7.79 (10.237.7.79) 56(84) bytes of data.
From 10.237.7.78 icmp_seq=1 Destination Host Unreachable
From 10.237.7.78 icmp_seq=2 Destination Host Unreachable
From 10.237.7.78 icmp_seq=3 Destination Host Unreachable
From 10.237.7.78 icmp_seq=4 Destination Host Unreachable
--- 10.237.7.79 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3053ms
Bây giờ hãy chạy Nginx:
/usr/local/nginx_fstack/sbin/nginx
Bạn có thể xem log ở /usr/local/nginx_fstack/logs/error.log
hoặc /usr/local/nginx_fstack/logs/access.log
(file access.log
chỉ xuất hiện log khi có client request vào webserver).
Ví dụ đoạn log dưới là từ F-Stack khi nó khởi động ứng dụng Nginx, sử dụng DPDK (Data Plane Development Kit).
shell> tail -f /usr/local/nginx_fstack/logs/error.log
TELEMETRY: No legacy callbacks, legacy socket not created
2024/12/06 10:10:41 [notice] 22127#0: signal process started
EAL: Detected CPU lcores: 4
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: VFIO support initialized
EAL: Probe PCI driver: net_vmxnet3 (15ad:07b0) device: 0000:0b:00.0 (socket -1)
TELEMETRY: No legacy callbacks, legacy socket not created
TELEMETRY: No legacy callbacks, legacy socket not created
: DPDK không tạo socket legacy vì không có callback nào yêu cầu. Điều này thường xảy ra trong các phiên bản mới của DPDK, nơi việc xử lý dữ liệu được cải thiện và không còn phụ thuộc vào cách giao tiếp cũ. Đây là thông báo bình thường và không ảnh hưởng đến hoạt động.
2024/12/06 10:10:41 [notice] 22127#0: signal process started
: Quá trình signal của Nginx được khởi động. Đây là bước khởi đầu của các worker process trong Nginx, nơi các tín hiệu (như reload, quit, v.v.) được xử lý. Đây là một thông báo của Nginx, không phải lỗi.
EAL: Detected CPU lcores: 4
: EAL (Environment Abstraction Layer) của DPDK phát hiện hệ thống có 4 lõi CPU logic (logical cores). Đây là thông tin quan trọng để DPDK cấu hình các thread cho xử lý gói tin.
EAL: Detected NUMA nodes: 1
Hệ thống sử dụng một node NUMA (Non-Uniform Memory Access). Điều này có nghĩa tất cả CPU và bộ nhớ đều nằm trên cùng một node. Với NUMA, hiệu năng tốt nhất đạt được khi các tài nguyên được sử dụng hiệu quả trên từng node.
EAL: Detected static linkage of DPDK
: DPDK được biên dịch và liên kết vào ứng dụng (F-Stack/Nginx). Điều này giúp ứng dụng không cần thư viện DPDK độc lập khi chạy. Đây là thông báo về cách DPDK được tích hợp vào ứng dụng.
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
: DPDK đã tạo một socket đa tiến trình tại /var/run/dpdk/rte/mp_socket
. Socket này cho phép các tiến trình DPDK giao tiếp với nhau. Điều này cần thiết cho các ứng dụng hỗ trợ nhiều worker process (như Nginx).
EAL: Selected IOVA mode 'PA'
: IOVA mode (Input-Output Virtual Addressing) được chọn là ‘PA’ (Physical Address). Chế độ này sử dụng địa chỉ vật lý thay vì địa chỉ ảo, phù hợp cho hầu hết các thiết bị PCIe. Điều này tối ưu hóa việc giao tiếp giữa DPDK và phần cứng mạng.
EAL: VFIO support initialized
: DPDK đã khởi tạo hỗ trợ VFIO (Virtual Function I/O). Đây là cơ chế giao tiếp an toàn và hiệu quả giữa kernel và các thiết bị PCIe. VFIO cần thiết khi bạn sử dụng NIC (Network Interface Card) được ánh xạ vào không gian người dùng (user space).
EAL: Probe PCI driver: net_vmxnet3 (15ad:07b0) device: 0000:0b:00.0 (socket -1)
: DPDK tìm thấy một NIC với driver net_vmxnet3 (VMware VMXNET3). Thiết bị này có PCI ID 15ad:07b0
và nằm ở địa chỉ PCI 0000:0b:00.0
. Driver net_vmxnet3
của DPDK đã sẵn sàng quản lý NIC này.
Kiểm tra trạng thái DPDK và F-Stack:
shell> ps -aef | grep nginx
root 22011 1 0 09:14 ? 00:00:00 nginx: master process /usr/local/nginx_fstack/sbin/nginx
root 22012 22011 97 09:14 ? 00:00:08 nginx: worker process
root 22017 1567 0 09:14 pts/1 00:00:00 grep nginx
Hãy kiểm tra lại kết quả ICMP bạn thấy ping thành công.
shell> ping -c 4 10.237.7.79
PING 10.237.7.79 (10.237.7.79) 56(84) bytes of data.
64 bytes from 10.237.7.79: icmp_seq=1 ttl=64 time=0.442 ms
64 bytes from 10.237.7.79: icmp_seq=2 ttl=64 time=0.145 ms
64 bytes from 10.237.7.79: icmp_seq=3 ttl=64 time=0.108 ms
64 bytes from 10.237.7.79: icmp_seq=4 ttl=64 time=0.090 ms
--- 10.237.7.79 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3052ms
rtt min/avg/max/mdev = 0.090/0.196/0.442/0.143 ms
Kiểm tra kết quả curl vào webserver sử dụng IP của F-Stack quản lý bạn thấy kết quả resolve thành công.
shell> curl -v http://10.237.7.79
* Uses proxy env variable no_proxy == 'localhost,127.0.0.1'
* Uses proxy env variable http_proxy == 'http://10.237.7.250:3128'
* Trying 10.237.7.250:3128...
* Connected to (nil) (10.237.7.250) port 3128 (#0)
> GET http://10.237.7.79/ HTTP/1.1
> Host: 10.237.7.79
> User-Agent: curl/7.81.0
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.25.2
< Date: Fri, 06 Dec 2024 09:16:10 GMT
< Content-Type: application/octet-stream
< Content-Length: 602
< X-Cache: MISS from localhost
< X-Cache-Lookup: HIT from localhost:3128
< Via: 1.1 localhost (squid/5.8)
< Connection: keep-alive
<
<title>Welcome to F-Stack Nginx!</title>
* Connection #0 to host (nil) left intact
pad data:0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
Lưu ý rằng khi bạn sử dụng igb_uio
hoặc vfio-pci
làm driver cho card mạng, kernel không quản lý card này nữa và bạn sẽ không thấy địa chỉ IP hay trạng thái của card trong ip a
hoặc ifconfig
và thậm chỉ netstat bạn cũng không thấy listen port 80 luôn nhé.
shell> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:80:d0:38 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 10.237.7.78/24 brd 10.237.7.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe80:d038/64 scope link
valid_lft forever preferred_lft forever
shell> netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1357/sshd: /usr/sbi
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 986/systemd-resolve
tcp6 0 0 :::22 :::* LISTEN 1357/sshd: /usr/sbi
Chú ý
Nếu bạn chỉ thay đổi các tham số không liên quan đến DPDK, như worker_processes
hoặc worker_connections
trong nginx.conf
, bạn có thể sử dụng lệnh reload.
/usr/local/nginx_fstack/sbin/nginx -s reload
Tuy nhiên, khi thay đổi các tham số liên quan đến f-stack.conf
(như ip_address
, port
, hoặc gateway
), bạn cần dừng và khởi động lại hoàn toàn.
4. Ví dụ triển khai trang web.
Mình tạo thư mục /home/www/ để chứa source web và truyền vào nội dung website như dưới.
mkdir -p /home/www/
echo 'Chào mừng bạn đến với website của tôi' > /home/www/index.html
Mình sẽ sửa file config mặc định với nội dung như sau. Chi tiết các config của nginx.conf các bạn có thể xem các bài khác nói về webserver, mình đã giải thích rất kỹ ở các bài đó. Bài này mình chỉ tập trung vào F-Stack mà thôi.
cat > /usr/local/nginx_fstack/conf/nginx.conf << 'OEF'
user root;
worker_processes 1;
fstack_conf f-stack.conf;
events {
worker_connections 102400;
use kqueue;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile off;
keepalive_timeout 65;
access_log /var/log/nginx/access.log combined;
error_log /var/log/nginx/error.log error;
server {
listen 80;
server_name hoanghd.com;
proxy_redirect off;
root /home/www/;
index index.html;
charset utf-8;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering on;
proxy_connect_timeout 3600s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
client_max_body_size 10m;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Content-Security-Policy upgrade-insecure-requests;
}
}
}
OEF
Tạo thư mục lưu log nếu chưa có.
mkdir /var/log/nginx/
Sử dụng lệnh /usr/local/nginx_fstack/sbin/nginx -t
để kiểm tra cú pháp file config.
shell> /usr/local/nginx_fstack/sbin/nginx -t
nginx: the configuration file /usr/local/nginx_fstack/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx_fstack/conf/nginx.conf test is successful
Không có lỗi cú pháp, sử dụng lệnh nginx -s reload để áp dụng config Nginx sau khi thay đổi.
/usr/local/nginx_fstack/sbin/nginx -s reload
Kết quả.

Kết quả của file log nhé.
shell> tail -f /var/log/nginx/access.log
10.237.7.250 - - [06/Dec/2024:10:07:51 +0000] "GET / HTTP/1.1" 200 51 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15"