Tại sao Unicast gặp giới hạn khi mở rộng quy mô
Phát trực tiếp một luồng video tới hàng chục máy trạm qua unicast sẽ gây lãng phí lượng băng thông khổng lồ. Giả sử 120 nhân viên cùng theo dõi một buổi phát sóng nội bộ chuẩn 1080p với bitrate 8 Mbps. Máy chủ media của bạn sẽ phải đẩy gần 1 Gbps (960 Mbps) qua một giao diện mạng duy nhất. Đường truyền uplink của switch sẽ nhanh chóng bị bão hòa, độ trễ tăng vọt và hiện tượng rớt khung hình (frame drop) lập tức xảy ra.
Broadcast cũng không thể giải quyết được vấn đề này. Các router được thiết kế để chủ động loại bỏ các gói tin broadcast tại ranh giới subnet nhằm ngăn chặn các cơn bão broadcast (broadcast storm) làm tê liệt toàn bộ hệ thống mạng.
Multicast chính là giải pháp thu hẹp khoảng cách này. Máy chủ media chỉ cần gửi duy nhất một luồng dữ liệu tới một địa chỉ multicast lớp D (chẳng hạn như 239.255.1.100). Các switch và router hạ lưu sẽ chỉ nhân bản (replicate) các gói tin này tới các phân đoạn vật lý có máy nhận đang hoạt động, thông qua việc theo dõi thành viên bằng giao thức IGMP (Internet Group Management Protocol).
Nhân Linux mặc định xử lý định tuyến unicast rất dễ dàng. Tuy nhiên, nó sẽ không chuyển tiếp lưu lượng multicast giữa các giao diện mạng nếu không có một tiến trình định tuyến (routing daemon) chuyên dụng. PIM-SM (Protocol Independent Multicast – Sparse Mode) đóng vai trò là giao thức tiêu chuẩn trong trường hợp này. Giao thức này giả định rằng số lượng máy nhận là thưa thớt và chỉ xây dựng cây phân phối (distribution tree) ngược về nguồn phát khi có một máy chủ gửi yêu cầu nhận luồng.
Chúng ta sử dụng pimd, một daemon PIM-SM đã được kiểm chứng thực tế, ban đầu được viết cho BSD và hiện được duy trì cho Linux bởi Joachim Nilsson (troglobit). Nó xử lý các luồng MPEG-TS bitrate cao, camera giám sát và lưu lượng chuyển tiếp RTSP với mức tiêu thụ CPU cực kỳ thấp.
Điều kiện tiên quyết & Thiết lập Kernel
Trước khi cấu hình pimd, hãy kiểm tra các cờ biên dịch của kernel và tinh chỉnh các tham số hệ thống.
1. Kiểm tra hỗ trợ Multicast trong Kernel
Đảm bảo rằng kernel đang chạy được biên dịch có hỗ trợ định tuyến multicast:
grep -E "CONFIG_IP_MROUTE|CONFIG_IP_PIMSM" /boot/config-$(uname -r)
Ubuntu, Debian, AlmaLinux và Rocky Linux đều kích hoạt các tùy chọn này theo mặc định. Hãy xác nhận rằng cả hai cờ đều trả về =y hoặc =m:
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
2. Cấu hình các thiết lập Sysctl
Định tuyến multicast có hai điểm bẫy sysctl phổ biến: reverse path filtering và trạng thái chỉ đọc (read-only) của mc_forwarding. Đừng cố gán giá trị net.ipv4.conf.all.mc_forwarding = 1 trực tiếp bằng tay; kernel sẽ từ chối việc ghi này và sẽ tự động kích hoạt nó khi pimd khởi tạo socket định tuyến multicast (MRT_INIT).
Tuy nhiên, bạn bắt buộc phải bật tính năng chuyển tiếp IPv4 tiêu chuẩn và tắt chế độ lọc đường dẫn ngược nghiêm ngặt (strict Reverse Path Filtering – RPF). Chế độ strict RPF thường khiến kernel loại bỏ các luồng multicast đến nếu bảng định tuyến unicast của bạn không duy trì một tuyến đường đối xứng quay trở lại bộ mã hóa (encoder).
Tạo tệp /etc/sysctl.d/99-multicast.conf:
sudo bash -c 'cat <<EOF > /etc/sysctl.d/99-multicast.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0
net.ipv4.conf.eth2.rp_filter = 0
EOF'
sudo sysctl --system
3. Cài đặt pimd
Trên Debian 11/12 và Ubuntu 22.04/24.04, cài đặt gói trực tiếp:
sudo apt update
sudo apt install -y pimd
Để biên dịch phiên bản upstream mới nhất từ mã nguồn trên các hệ thống nền tảng RHEL hoặc hệ thống tối giản:
sudo apt install -y build-essential automake autoconf pkg-config
git clone https://github.com/troglobit/pimd.git
cd pimd
./autogen.sh
./configure --prefix=/usr --sysconfdir=/etc
make
sudo make install
Mô hình mạng & Cấu hình
Dưới đây là mô hình triển khai của chúng ta:
- eth1 (192.168.10.1/24): Subnet nguồn video (IP của encoder:
192.168.10.50) - eth2 (192.168.20.1/24): Subnet máy khách (Các máy trạm nhận luồng:
192.168.20.0/24) - Kênh Multicast:
239.255.1.100lắng nghe trên cổng UDP5004
1. Chỉnh sửa /etc/pimd.conf
Theo mặc định, pimd sẽ cố gắng chạy trên mọi giao diện mạng đang hoạt động mà nó phát hiện được, bao gồm cả cổng loopback và cổng quản trị. Ban đầu hãy vô hiệu hóa tất cả các giao diện, sau đó kích hoạt rõ ràng chỉ những giao diện dùng để phát luồng:
sudo nano /etc/pimd.conf
Thêm các quy tắc sau vào tệp:
# /etc/pimd.conf
# Bỏ qua các giao diện mạng trừ khi được khai báo rõ ràng
default-phyint-status disable
# Giao diện mạng đầu vào từ bộ mã hóa IPTV
phyint eth1 enable
# Giao diện mạng đầu ra tới các máy trạm của người dùng
phyint eth2 enable
# Cấu hình máy chủ này làm Rendezvous Point (RP)
# Xử lý dải multicast có phạm vi quản trị 239.0.0.0/8
rp-candidate eth1 priority 20 time 30
group-prefix 239.0.0.0 masklen 8
# Cấu hình máy chủ này làm Bootstrap Router (BSR) candidate
bsr-candidate eth1 priority 5
2. Cấu hình quy tắc Netfilter / iptables
Tường lửa của Linux mặc định sẽ chặn các gói tin multicast không mong muốn và các tín hiệu điều khiển. Bạn cần cho phép IGMP (giao thức 2), các thông điệp điều khiển PIM (giao thức 103) và các gói tin UDP multicast được định tuyến:
# Chấp nhận lưu lượng điều khiển IGMP và PIM cục bộ
sudo iptables -A INPUT -p igmp -j ACCEPT
sudo iptables -A INPUT -p 103 -j ACCEPT
# Cho phép chuyển tiếp PIM giữa các router ngang hàng
sudo iptables -A FORWARD -p 103 -j ACCEPT
# Chuyển tiếp các gói tin UDP multicast từ subnet nguồn sang subnet máy khách
sudo iptables -A FORWARD -i eth1 -o eth2 -d 239.0.0.0/8 -p udp --dport 5004 -j ACCEPT
3. Khởi động và kích hoạt Daemon
Khởi chạy pimd và kiểm tra trạng thái systemd để xác nhận daemon đã liên kết thành công với các giao diện mạng:
sudo systemctl restart pimd
sudo systemctl enable pimd
sudo systemctl status pimd
Kiểm tra & Gỡ lỗi
Thực hiện các bước kiểm tra sau để xác nhận các gói tin multicast được chuyển tiếp giữa các subnet mà không bị rớt gói.
1. Kiểm tra các giao diện ảo Multicast (VIF)
Kiểm tra bảng giao diện ảo multicast của kernel:
cat /proc/net/ip_mr_vif
Bạn sẽ thấy eth1 được gán cho VIF 0 và eth2 được gán cho VIF 1. Khi quá trình phát luồng bắt đầu, cột PktsIn trên eth1 và cột PktsOut trên eth2 sẽ tăng dần.
2. Kiểm tra bộ nhớ đệm chuyển tiếp Multicast của Kernel
Kiểm tra các tuyến định tuyến multicast hiện tại bằng iproute2:
ip mroute show
Khi một máy khách tham gia nhóm và nguồn phát đang hoạt động, kernel sẽ hiển thị một tuyến (S,G) đã được thiết lập:
(192.168.10.50, 239.255.1.100) Iif: eth1 Oifs: eth2
Nếu kết quả hiển thị Oifs: unresolved hoặc không liệt kê eth2, nghĩa là máy khách của bạn chưa gửi bản tin IGMP report, hoặc tường lửa đã chặn bản tin này.
3. Kiểm tra trạng thái nội bộ của pimd
Buộc pimd xuất thông tin bảng định tuyến, bộ đếm thời gian của nhóm và danh sách các lân cận (neighbor) bằng cách gửi tín hiệu USR1:
sudo killall -USR1 pimd
cat /var/run/pimd/pimd.dump 2>/dev/null || cat /var/tmp/pimd.dump
Hãy tìm các phần (*,G) và (S,G). Chúng xác nhận xem router đã tự bầu chọn làm RP và đã đăng ký thành công bộ mã hóa nguồn hay chưa.
4. Chạy kiểm thử End-to-End
Bạn không cần một bộ mã hóa phần cứng đắt tiền để kiểm thử mô hình này. Chỉ với hai lệnh kiểm tra đơn giản là có thể xác minh router của bạn có hoạt động hay không.
Bước 1: Tham gia nhóm multicast trên máy khách (192.168.20.50)
# Yêu cầu tham gia nhóm và lắng nghe trên cổng UDP 5004 bằng socat
socat - UDP4-RECV:5004,ip-add-membership=239.255.1.100:192.168.20.50
Ngoài ra, bạn có thể mở VLC trên máy khách và truy cập Media > Open Network Stream với URL udp://@239.255.1.100:5004.
Bước 2: Phát luồng video mẫu (color bars) từ máy nguồn (192.168.10.50)
Điểm mấu chốt quan trọng: hãy đặt chỉ số TTL của multicast lớn hơn 1. Giá trị TTL multicast mặc định ở nhiều công cụ là 1, đồng nghĩa với việc router đầu tiên gặp phải sẽ lập tức loại bỏ gói tin.
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
-vcodec libx264 -preset ultrafast -b:v 2500k -f mpegts \
"udp://239.255.1.100:5004?pkt_size=1316&ttl=16"
Xác nhận gói tin đã đến trên giao diện mạng đầu ra của router bằng tcpdump:
sudo tcpdump -n -i eth2 host 239.255.1.100 and udp port 5004
Nếu các gói tin xuất hiện trên eth2, máy chủ Linux của bạn đã định tuyến thành công video multicast qua các ranh giới mạng với độ trễ thấp và hoàn toàn không làm tràn lưu lượng không cần thiết sang các subnet khác.

