Menggunakan DPDK
Halaman ini menjelaskan cara menggunakan Data Plane Development Kit (DPDK) di instance Compute Engine U4C.
Tentang DPDK melalui AF_XDP
Data Plane Development Kit (DPDK) adalah framework untuk aplikasi yang membutuhkan performa tinggi dan memerlukan pemrosesan paket yang cepat, latensi rendah, dan performa yang konsisten. DPDK mengabaikan stack jaringan kernel Linux dan berjalan langsung di ruang pengguna. Anda dapat menjalankan DPDK di instance U4C menggunakan arsitektur AF_XDP.
DPDK menyediakan Driver Mode Polling AF_XDP (PMD), yang merupakan perangkat virtual (vdev) yang memungkinkan aplikasi DPDK berjalan di atas AF_XDP dalam mode salin atau mode tanpa salin. Untuk mengetahui informasi selengkapnya, lihat
Driver Mode Polling AF_XDP dalam
dokumentasi DPDK. Tidak seperti
deployment umum di Compute Engine,
DPDK melalui AF_XDP di instance U4C tidak memerlukan konfigurasi VFIO, UIO, atau
dpdk-devbind.py.
Penggunaan DPDK dengan Solusi ULL mencakup dukungan untuk pengarahan alur. Anda dapat mengabaikan hashing Receive Side Scaling (RSS) default dengan mengarahkan alur traffic tertentu langsung ke antrean penerimaan (RX)yang ditentukan. Solusi ULL mendukung pengarahan alur 3-tuple (protokol, alamat IP tujuan, dan port tujuan) untuk traffic unicast dan multicast ULL.
Sebelum memulai
Sebelum menggunakan DPDK di instance Compute Engine U4C, Anda harus memenuhi persyaratan berikut.
Membuat instance U4C
Jika belum melakukannya, buat instance bare metal U4C. Lihat Membuat ULL instance Compute Engine.
Menghubungkan ke instance menggunakan SSH
Jika belum melakukannya, hubungkan ke instance menggunakan SSH.
Beralih ke pengguna root
Perintah dan skrip dalam prosedur berikut mengubah setelan tingkat sistem, parameter kernel, dan antarmuka jaringan. Agar berhasil menjalankannya, Anda harus mengeksekusinya sebagai pengguna root. Anda dapat beralih ke shell root dengan
menjalankan sudo su, atau menambahkan sudo sebelum menjalankan perintah sesuai kebutuhan.
Menginstal DPDK di instance U4C
Untuk menginstal DPDK di instance U4C, ikuti langkah-langkah berikut:
Konfigurasikan dependensi untuk penginstalan DPDK:
apt-get update && apt-get upgrade -yq apt-get install -yq build-essential ninja-build python3-pip \ linux-headers-$(uname -r) pkg-config libnuma-dev pip install pyelftools mesonInstal DPDK.
wget https://fast.dpdk.org/rel/dpdk-VERSION.tar.xz tar xvf dpdk-VERSION.tar.xz cd dpdk-VERSION
Ganti
VERSIONdengan versi DPDK yang ingin Anda instal, seperti26.07. Jika diperlukan, lihat halaman Download DPDK.Untuk membuat DPDK dengan contoh:
meson setup -Dexamples=all build ninja -C build install; ldconfig
Mengonfigurasi antarmuka jaringan untuk AF_XDP
Untuk menggunakan AF_XDP di Google Virtual NIC (gVNIC), Anda harus menyesuaikan fitur driver default untuk menyiapkan antarmuka jaringan.
Anda dapat melakukan langkah-langkah ini secara manual atau menggunakan skrip konfigurasi otomatis. Pilih salah satu tab berikut:
Manual
Ikuti langkah-langkah berikut untuk setiap antarmuka jaringan yang ingin Anda konfigurasi.
Kurangi jumlah antrean RX dan TX: gVNIC secara default menggunakan jumlah antrean RX dan TX maksimum yang didukung, tetapi Anda harus menguranginya hingga setengah untuk memastikan ada cukup antrean TX untuk traffic kernel normal.
ethtool -L NIC_NAME rx NUM_SOCKETS \ tx NUM_SOCKETS
Ganti kode berikut:
NIC_NAME: nama OS antarmuka jaringan, sepertieth1.NUM_SOCKETS: jumlah soket AF_XDP yang akan dikonfigurasi. Tetapkan nilai ini tidak lebih dari setengah antrean maksimum untuk antarmuka. Untuk instance U4C, nilai ini biasanya adalah8(setengah dari 16 antrean default). Anda dapat memverifikasi antrean maksimum dengan menjalankanethtool -l NIC_NAME.
Nonaktifkan GRO dan LRO hardware: Karena gVNIC tidak mendukung XDP multi-buffer, Anda harus menonaktifkan Large Receive Offload (LRO) dan Generic Receive Offload (GRO) hardware:
ethtool -K NIC_NAME rx-gro-hw off ethtool -K NIC_NAME lro off
Kurangi panjang buffer RX: Secara default, driver yang lebih baru memposting buffer 4 KB (4.096 byte) ke antarmuka jaringan untuk RX, tetapi XDP memerlukan panjang buffer
2048:ethtool -G NIC_NAME rx-buf-len 2048
Skrip
Atau, Anda dapat menjalankan skrip Bash berikut untuk setiap antarmuka jaringan yang ingin Anda konfigurasi. Skrip ini secara otomatis menyiapkan a antarmuka jaringan tertentu untuk XDP dengan mengurangi jumlah antrean, menonaktifkan offload, dan menyesuaikan panjang buffer RX:
#!/bin/bash # Usage example: NUM_SOCKETS=8 prep_xdp.sh eth0 DEV=$1 NUM_SOCKETS=${NUM_SOCKETS=1} # Reduce RX/TX queue counts to the number of AF_XDP sockets ethtool -L $DEV rx $NUM_SOCKETS tx $NUM_SOCKETS # Disable LRO/HW-gro OFFLOAD=$(ethtool -k $DEV | \ grep "rx-gro-hw\|large-receive-offload" | \ grep -v fixed | cut -d ":" -f 1) ethtool -K $DEV ${OFFLOAD} off # Reduce RX buffer length to 2048 ethtool -G $DEV rx-buf-len 2048
Menjalankan aplikasi DPDK
Untuk menggunakan PMD AF_XDP, sertakan flag --vdev dalam argumen Environment Abstraction Layer (EAL) aplikasi DPDK Anda.
Contoh perintah berikut mencakup beberapa parameter utama. Untuk mengetahui informasi mendetail tentang penyiapan dan parameter, lihat Driver Mode Polling AF_XDP dalam dokumentasi DPDK.
DPDK_APPLICATION -a PCIE_BDF \ --vdev=net_af_xdp,iface=NIC_NAME,queue_count=NUM_SOCKETS,start_queue=START_QUEUE,xdp_prog=XDP_PROG \ -- APPLICATION_ARGS
Ganti kode berikut:
DPDK_APPLICATION: biner aplikasi DPDK yang akan dijalankan.PCIE_BDF: alamat PCI antarmuka jaringan. Anda dapat menemukan nilai ini dengan menjalankanethtool -i NIC_NAMEdan memeriksa nilaibus-info, seperti0000:00:04.0.NIC_NAME: nama OS antarmuka jaringan, sepertieth1.NUM_SOCKETS: jumlah soket AF_XDP yang akan dibuka. Setiap soket terlampir ke satu pasangan antrean. Nilai ini harus cocok dengan jumlah antrean yang Anda konfigurasi di antarmuka.START_QUEUE: indeks antrean awal untuk soket AF_XDP.XDP_PROG: program XDP kustom yang akan dijalankan pada paket yang diterima. Jika dihilangkan, DPDK akan menggunakan program XDP default yang disediakan olehlibxdp.APPLICATION_ARGS: argumen khusus untuk aplikasi DPDK Anda.
Menggunakan fitur driver
Bagian ini memberikan informasi penggunaan untuk pengarahan alur dan stempel waktu RX.
Pengarahan alur
Anda dapat menggunakan pengarahan alur dengan XDP untuk mengarahkan paket aplikasi ke subset antrean tertentu, sehingga antrean yang tersisa dapat digunakan untuk traffic kernel. Bagian berikut menjelaskan dua pendekatan yang dapat Anda gunakan untuk pemrograman aturan alur.
Memprogram pengarahan alur terlebih dahulu (direkomendasikan)
Karena pemrograman alur langsung menggunakan panggilan ioctl tidak didukung oleh PMD AF_XDP dan memerlukan modifikasi aplikasi DPDK Anda, sebaiknya program aturan alur Anda terlebih dahulu menggunakan ethtool sebelum memulai aplikasi.
Misalnya, untuk memprogram aturan alur yang mengarahkan traffic UDP IPv4 ke antrean 0:
ethtool -N NIC_NAME flow-type udp4 \ dst-ip DST_IP dst-port DST_PORT action 0 loc 0
Ganti kode berikut:
NIC_NAME: nama OS antarmuka jaringan, sepertieth1.DST_IP: alamat IP tujuan traffic yang akan diarahkan.DST_PORT: port tujuan traffic yang akan diarahkan.
Memprogram aturan alur langsung
PMD AF_XDP tidak mendukung pemrograman alur langsung. Untuk menggunakan metode ini, Anda harus mengubah aplikasi DPDK untuk mengirim panggilan ioctl ethtool secara manual.
Sebaiknya hindari pendekatan ini kecuali jika aplikasi Anda menangani sejumlah besar koneksi sementara. gVNIC mendukung hingga 20.000 aturan pengarahan alur 3-tuple; jika Anda memerlukan lebih sedikit aturan dan mengetahui alamat IP dan port tujuan Anda terlebih dahulu, program aturan Anda terlebih dahulu.
Jika Anda harus memprogram aturan secara dinamis, lihat contoh kode C berikut:
Luaskan untuk melihat contoh kode C
struct flow_rule_info { uint32_t src_ip; uint32_t dst_ip; uint16_t src_port; uint16_t dst_port; uint32_t target_queue; uint32_t rule_id; } int add_flow_rule(const char *ifname, struct flow_rule_info *rule_info, bool is_5tuple) { struct ethtool_rxnfc cmd; struct ifreq ifr; int fd; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { fprintf(stderr, "Failed to open socket: %s", strerror(fd)); return -1; } memset(&cmd, 0, sizeof(cmd)); memset(&ifr, 0, sizeof(ifr)); cmd.cmd = ETHTOOL_SRXCLSRLINS; cmd.fs.flow_type = UDP_V4_FLOW; cmd.fs.h_u.udp_ip4_spec.ip4dst = rule_info->dst_ip; cmd.fs.h_u.udp_ip4_spec.pdst = htons(rule_info->dst_port); cmd.fs.m_u.udp_ip4_spec.ip4dst = 0xFFFFFFFF; cmd.fs.m_u.udp_ip4_spec.pdst = 0xFFFF; if (is_5tuple) { cmd.fs.h_u.udp_ip4_spec.ip4src = rule_info->src_ip; cmd.fs.h_u.udp_ip4_spec.psrc = htons(rule_info->src_port); cmd.fs.m_u.udp_ip4_spec.ip4src = 0xFFFFFFFF; cmd.fs.m_u.udp_ip4_spec.psrc = 0xFFFF; } cmd.fs.ring_cookie = rule_info->target_queue; cmd.fs.location = rule_info->rule_id; strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); ifr.ifr_data = (void *)&cmd; int ret = ioctl(fd, SIOCETHTOOL, &ifr); if (ret) fprintf(stderr, "Failed to send ioctl: %s\n", strerror(errno)); close(fd); return ret; } int try_add_xdp_flow_rule(int port, struct flow_rule_info *rule_info) { char dev_name[RTE_ETH_NAME_MAX_LEN]; char *af_xdp_driver = "net_af_xdp"; struct rte_eth_dev_info dev_info; int err; if (!rte_eth_dev_is_valid_port(port)) return -1; err = rte_eth_dev_info_get(port, &dev_info); if (err) { fprintf(stderr, "Error getting info for port %d: %s\n", port, strerror(err)); return retval; } if (strncmp(dev_info.driver_name, af_xdp_driver, strlen(af_xdp_driver)) != 0) { fprintf(stderr, "Not an AF_XDP vdev!\n"); return -EINVAL; } err = rte_eth_dev_get_name_by_port(port, dev_name); if (retval) { fprintf(stderr, "Failed to get dev_name: %s\n", strerror(err)); return retval; } /* replace ens4 with correct ifname; must be passed in as application argument */ err = add_flow_rule("ens4", rule_info)); if (err) fprintf("Failed to add flow rule: %s\n", strerror(err)); return err; } /* From somewhere in the application: */ int application_func(...) { ... struct flow_rule_info *rule_info { .src_ip = 0x0a000001, .dst_ip = 0x0a000002, .src_port = 0x1110, .uint16_t dst_port = 0x1011, .uint32_t target_queue = 0, .uint32_t rule_id = 1, }; try_add_xdp_flow_rule(xdp_port_id, &rule_info, /*is_5tuple=*/false); ... }
Pemrograman RSS
Saat menggunakan pengarahan alur, RSS dapat membantu memberikan isolasi traffic yang lebih baik.
Seperti pengarahan alur, Anda dapat mengonfigurasi RSS menggunakan ethtool. Sebaiknya konfigurasi RSS sebelum menjalankan aplikasi Anda.
Contoh berikut menunjukkan cara mengonfigurasi RSS agar berfungsi dengan AF_XDP:
# Example: Kernel queues 0-3, XDP queues 4-7 NUM_SOCKETS=4 bash prep_xdp.sh eth0 # Program flow rules ethtool -N eth0 flow-type udp4 dst-ip DST_IP dst-port DST_PORT_0 action 4 loc 0 ethtool -N eth0 flow-type udp4 dst-ip DST_IP dst-port DST_PORT_1 action 5 loc 1 ethtool -N eth0 flow-type udp4 dst-ip DST_IP dst-port DST_PORT_2 action 6 loc 2 ethtool -N eth0 flow-type udp4 dst-ip DST_IP dst-port DST_PORT_3 action 7 loc 3 # If there are more ports that the application polls on, flow rules can be added in a round-robin fashion in a script. # Program RSS ethtool -X eth0 start 0 equal 4 # Run the application ./path/to/application -a 0000:00:03.0 --vdev net_af_xdp,iface=eth0,start_queue=4,queue_count=4 -- APPLICATION_ARGS
Stempel waktu RX
Meskipun stempel waktu RX tidak didukung di repositori DPDK upstream untuk PMD AF_XDP, Anda dapat menggunakan stempel waktu RX dengan melakukan hal berikut:
Terapkan patch yang diperlukan ke pohon sumber DPDK dan kompilasi ulang sumber DPDK dan aplikasi Anda. Patch ini menambahkan dukungan untuk
rte_eth_read_clockdan stempel waktu RX dimbufsyang diterima.Gunakan program XDP yang memuat stempel waktu ke dalam metadata.
Berikan parameter
vdevAF_XDP tambahan berikut saat memulai aplikasi DPDK Anda:xdp_meta_rx_ts_offset: offset byte dari awal metadata XDP tempat nilai stempel waktu RX 64-bit berada.xdp_meta_valid_hint_offset: (Opsional) offset byte yang mencakup kolom flag 1 byte yang menunjukkan apakah stempel waktu valid.xdp_meta_rx_ts_valid_mask: (Opsional) bitmask yang digunakan untuk mengekstrak bit flag yang valid.Jika
ctxadalah awal metadata, nilai(ctx->data_meta + xdp_meta_valid_hint_offset) & xdp_meta_rx_ts_valid_maskakan menjelaskan apakah stempel waktu valid.
Langkah berikutnya
- Untuk menyinkronkan jam instance Anda dengan jam NIC fisik server host -nya, lihat Mengonfigurasi waktu yang akurat.