Công cụ lưu lượng truy cập mạng eBPF sử dụng sự kết hợp giữa việc triển khai không gian người dùng và nhân để theo dõi mức sử dụng mạng trên thiết bị kể từ lần khởi động thiết bị gần đây nhất. Nó cung cấp thêm chức năng như gắn thẻ ổ cắm, tách lưu lượng truy cập ở nền trước/nền sau và tường lửa theo UID để chặn các ứng dụng truy cập vào mạng tuỳ thuộc vào trạng thái điện thoại. Số liệu thống kê thu thập được từ công cụ này được lưu trữ trong một cấu trúc dữ liệu của nhân có tên là eBPF maps
và kết quả được các dịch vụ như NetworkStatsService
sử dụng để cung cấp số liệu thống kê lưu lượng truy cập liên tục kể từ lần khởi động gần đây nhất.
Ví dụ và nguồn
Các thay đổi về không gian người dùng chủ yếu nằm trong các dự án system/netd
và framework/base
. Quá trình phát triển đang được thực hiện trong AOSP, vì vậy, mã AOSP sẽ luôn được cập nhật. Nguồn chủ yếu nằm ở system/netd/server/TrafficController*
, system/netd/bpfloader
và system/netd/libbpf/
.
Một số thay đổi cần thiết về khung cũng nằm trong framework/base/
và system/core
.
Triển khai
Kể từ Android 9, các thiết bị Android chạy trên nhân 4.9 trở lên và ban đầu được phát hành cùng với bản phát hành P PHẢI sử dụng tính năng kế toán giám sát lưu lượng truy cập mạng dựa trên eBPF thay vì xt_qtaguid
. Cơ sở hạ tầng mới linh hoạt và dễ duy trì hơn, đồng thời không yêu cầu bất kỳ mã hạt nhân nào ngoài cây.
Sự khác biệt chính về thiết kế giữa tính năng giám sát lưu lượng truy cập cũ và eBPF được minh hoạ trong Hình 1.
Hình 1. Sự khác biệt giữa thiết kế giám sát lưu lượng truy cập cũ (bên trái) và eBPF (bên phải)
Thiết kế trafficController
mới cũng dựa trên bộ lọc eBPF cgroup
cho mỗi bộ lọc cũng như mô-đun xt_bpf
netfilter bên trong nhân. Các bộ lọc eBPF này được áp dụng trên tx/rx gói khi chúng đi qua bộ lọc. Bộ lọc cgroup
eBPF nằm ở lớp truyền tải và chịu trách nhiệm đếm lưu lượng truy cập theo UID phù hợp, tuỳ thuộc vào UID của ổ cắm cũng như chế độ cài đặt không gian người dùng.
xt_bpf
netfilter được kết nối tại chuỗi bw_raw_PREROUTING
và bw_mangle_POSTROUTING
, đồng thời chịu trách nhiệm đếm lưu lượng truy cập đối với giao diện chính xác.
Tại thời điểm khởi động, quy trình không gian người dùng trafficController
sẽ tạo các bản đồ eBPF được dùng để thu thập dữ liệu và ghim tất cả các bản đồ dưới dạng một tệp ảo tại sys/fs/bpf
.
Sau đó, quy trình đặc quyền bpfloader
sẽ tải chương trình eBPF được biên dịch trước vào hạt nhân và đính kèm chương trình đó vào cgroup
chính xác. Có một cgroup
gốc duy nhất cho tất cả lưu lượng truy cập, vì vậy, theo mặc định, tất cả quy trình đều phải có trong cgroup
đó.
Trong thời gian chạy, trafficController
có thể gắn/huỷ gắn thẻ một ổ cắm bằng cách ghi vào traffic_cookie_tag_map
và traffic_uid_counterSet_map
. NetworkStatsService
có thể đọc dữ liệu thống kê lưu lượng truy cập từ traffic_tag_stats_map
, traffic_uid_stats_map
và traffic_iface_stats_map
.
Ngoài chức năng thu thập số liệu thống kê về lưu lượng truy cập, bộ lọc trafficController
và cgroup
eBPF cũng chịu trách nhiệm chặn lưu lượng truy cập từ một số UID nhất định, tuỳ thuộc vào chế độ cài đặt điện thoại. Tính năng chặn lưu lượng truy cập mạng dựa trên UID là một tính năng thay thế cho mô-đun xt_owner
bên trong nhân và bạn có thể định cấu hình chế độ chi tiết bằng cách ghi vào traffic_powersave_uid_map
, traffic_standby_uid_map
và traffic_dozable_uid_map
.
Quy trình triển khai mới tuân theo quy trình triển khai mô-đun xt_qtaguid
cũ, do đó, TrafficController
và NetworkStatsService
sẽ chạy với quy trình triển khai cũ hoặc mới. Nếu sử dụng các API công khai, ứng dụng sẽ không gặp phải bất kỳ sự khác biệt nào cho dù xt_qtaguid
hay các công cụ eBPF được dùng trong nền.
Nếu nhân thiết bị dựa trên nhân chung Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 trở lên), thì bạn không cần sửa đổi HAL, trình điều khiển hoặc mã nhân để triển khai công cụ eBPF mới.
Yêu cầu
Cấu hình kernel PHẢI bật các cấu hình sau:
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
Kiểm thử cấu hình hạt nhân VTS rất hữu ích khi xác minh rằng bạn đã bật đúng cấu hình.
Quy trình ngừng sử dụng xt_qtaguid cũ
Công cụ eBPF mới đang thay thế mô-đun xt_qtaguid
và mô-đun xt_owner
mà công cụ này dựa trên. Chúng tôi sẽ bắt đầu xoá mô-đun xt_qtaguid
khỏi nhân Android và tắt các cấu hình không cần thiết của mô-đun này.
Trong bản phát hành Android 9, mô-đun xt_qtaguid
sẽ được bật trên tất cả các thiết bị, nhưng tất cả các API công khai trực tiếp đọc tệp proc mô-đun xt_qtaguid
đều được chuyển vào Dịch vụ NetworkManagement
.
Tuỳ thuộc vào phiên bản nhân của thiết bị và cấp độ API đầu tiên, Dịch vụ NetworkManagement
sẽ biết liệu các công cụ eBPF có được bật hay không và chọn mô-đun phù hợp để nhận cho từng số liệu thống kê về mức sử dụng mạng của ứng dụng. Các ứng dụng có SDK cấp 28 trở lên sẽ bị sepolicy chặn truy cập vào các tệp proc xt_qtaguid
.
Trong bản phát hành Android tiếp theo sau phiên bản 9, quyền truy cập của ứng dụng vào các tệp xt_qtaguid
proc đó sẽ bị chặn hoàn toàn và chúng tôi sẽ bắt đầu xoá mô-đun xt_qtaguid
khỏi các nhân chung mới của Android. Sau khi xoá, chúng tôi sẽ cập nhật cấu hình cơ sở của Android cho phiên bản nhân đó để tắt rõ ràng mô-đun xt_qtaguid
. Mô-đun xt_qtaguid
sẽ hoàn toàn không được dùng nữa khi yêu cầu về phiên bản nhân tối thiểu cho một bản phát hành Android là 4.9 trở lên.
Trong bản phát hành Android 9, chỉ những thiết bị ra mắt cùng với bản phát hành Android 9 mới bắt buộc phải có tính năng eBPF mới. Đối với những thiết bị được xuất xưởng cùng với một nhân có thể hỗ trợ các công cụ eBPF, bạn nên cập nhật nhân đó lên tính năng eBPF mới khi nâng cấp lên bản phát hành Android 9. Không có kiểm thử CTS nào để thực thi bản cập nhật đó.
Xác nhận kết quả
Bạn nên thường xuyên lấy các bản vá từ các hạt nhân chung của Android và Android AOSP main. Đảm bảo chế độ triển khai của bạn vượt qua các kiểm thử VTS và CTS hiện hành, netd_unit_test
và libbpf_test
.
Thử nghiệm
Có kernel net_tests để đảm bảo bạn đã bật các tính năng bắt buộc và các bản vá kernel bắt buộc đã được chuyển ngược. Các kiểm thử này được tích hợp trong các kiểm thử VTS của bản phát hành Android 9. Có một số kiểm thử đơn vị trong system/netd/
(netd_unit_test
và libbpf_test
). Có một số kiểm thử trong netd_integration_test
để xác thực hành vi tổng thể của công cụ mới.
CTS và trình xác minh CTS
Vì cả hai mô-đun giám sát lưu lượng truy cập đều được hỗ trợ trong bản phát hành Android 9, nên không có kiểm thử CTS nào bắt buộc triển khai mô-đun mới trên tất cả các thiết bị. Tuy nhiên, đối với các thiết bị có phiên bản nhân cao hơn 4.9 và ban đầu được phát hành cùng với bản phát hành Android 9 (tức là cấp độ API đầu tiên >= 28), có các kiểm thử CTS trên GSI để xác thực rằng mô-đun mới được định cấu hình chính xác. Bạn có thể dùng các bài kiểm thử CTS cũ như TrafficStatsTest
, NetworkUsageStatsTest
và CtsNativeNetTestCases
để xác minh hành vi nhất quán với mô-đun UID cũ.
Kiểm thử theo cách thủ công
Có một số kiểm thử đơn vị trong system/netd/
(netd_unit_test
, netd_integration_test
và libbpf_test
). Có hỗ trợ dumpsys để kiểm tra trạng thái theo cách thủ công. Lệnh dumpsys netd
cho biết trạng thái cơ bản của mô-đun trafficController
và liệu eBPF có được bật đúng cách hay không. Nếu eBPF được bật, lệnh dumpsys netd trafficcontroller
sẽ cho thấy nội dung chi tiết của từng bản đồ eBPF, bao gồm thông tin về socket được gắn thẻ, số liệu thống kê cho mỗi thẻ, UID và iface, cũng như thông tin trùng khớp về UID của chủ sở hữu.
Vị trí kiểm thử
Các bài kiểm thử CTS nằm ở:
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/android16-release/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/android16-release/tests/bpf_base_test.cpp
Các kiểm thử VTS nằm tại https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py.
Các bài kiểm thử đơn vị nằm ở: