Công cụ lưu lượng truy cập mạng eBPF sử dụng kết hợp việc triển khai hạt nhân và không gian người dùng để 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. API này cung cấp chức năng bổ sung như gắn thẻ với cổng, phân tách lưu lượng truy cập ở nền trước/nền và tường lửa theo UID để chặn ứng dụng truy cập mạng tuỳ thuộc vào trạng thái của đ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 hạt 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 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 này 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 có trong framework/base/
và system/core
.
Triển khai
Kể từ Android 9, các thiết bị Android chạy trên hạt nhân 4.9 trở lên và ban đầu được vận chuyển bằng 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 hơn và dễ bảo trì hơn, đồng thời không yêu cầu bất kỳ mã hạt nhân ngoài cây nào.
Hình 1 minh hoạ những điểm 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.
Hình 1. Sự khác biệt về 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 dựa trên bộ lọc eBPF trên mỗi cgroup
cũng như mô-đun netfilter xt_bpf
bên trong hạt nhân. Các bộ lọc eBPF này được áp dụng cho gói tx/rx khi chúng đi qua bộ lọc. Bộ lọc eBPF cgroup
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ắm cũng như chế độ cài đặt không gian người dùng.
Bộ lọc netfilter xt_bpf
được nối vào 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 trên 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 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 mọi lưu lượng truy cập, vì vậy, tất cả quy trình phải được đưa vào cgroup
đó theo mặc định.
Trong thời gian chạy, trafficController
có thể gắn thẻ/bỏ 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 hàm thu thập số liệu thống kê về lưu lượng truy cập, bộ lọc eBPF trafficController
và cgroup
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à tính năng thay thế mô-đun xt_owner
bên trong hạt 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
.
Cách triển khai mới tuân theo cách triển khai mô-đun xt_qtaguid
cũ, vì vậy, TrafficController
và NetworkStatsService
sẽ chạy bằng cách triển khai cũ hoặc mới. Nếu sử dụng API công khai, ứng dụng sẽ không gặp bất kỳ sự khác biệt nào khi sử dụng công cụ xt_qtaguid
hoặc eBPF ở chế độ nền.
Nếu nhân của thiết bị dựa trên nhân hệ điều hành Android phổ biến 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 hạt nhân 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 sẽ 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 sẽ thay thế mô-đun xt_qtaguid
và mô-đun xt_owner
dựa trên mô-đun này. Chúng ta sẽ bắt đầu xoá mô-đun xt_qtaguid
khỏi hạt nhân Android và tắt các cấu hình không cần thiết của mô-đun đó.
Trong bản phát hành Android 9, mô-đun xt_qtaguid
được bật trong tất cả thiết bị, nhưng tất 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 hạt nhân 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 để lấy cho mỗi 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 tệp proc xt_qtaguid
.
Trong bản phát hành Android tiếp theo sau Android 9, quyền truy cập của ứng dụng vào các tệp proc xt_qtaguid
đó sẽ bị chặn hoàn toàn. Chúng tôi sẽ bắt đầu xoá mô-đun xt_qtaguid
khỏi các hạt nhân phổ biến mới của Android. Sau khi xoá, chúng tôi sẽ cập nhật cấu hình cơ sở Android cho phiên bản nhân đó để tắt mô-đun xt_qtaguid
một cách rõ ràng. Mô-đun xt_qtaguid
sẽ không được dùng nữa khi yêu cầu phiên bản nhân tối thiểu cho 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ị chạy bằng 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 các thiết bị được vận chuyển với hạt nhân có thể hỗ trợ các công cụ eBPF, bạn nên cập nhật hạ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ó quy trình 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ừ hạt nhân Android phổ biến và hạt nhân chính Android AOSP. Đảm bảo quá trình triển khai của bạn vượt qua các bài 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á hạt nhân bắt buộc đã được điều chỉnh cho phiên bản cũ. Các chương trình kiểm thử này được tích hợp trong các chương trình 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.
Trình xác minh CTS và 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ó chương trình kiểm thử CTS nào để buộc triển khai mô-đun mới trên tất 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 ban đầu đi kèm 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ể sử dụng các chương trình kiểm thử CTS cũ như TrafficStatsTest
, NetworkUsageStatsTest
và CtsNativeNetTestCases
để xác minh hành vi cho 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
). Dumpsys hỗ trợ 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 chính xác hay không. Nếu eBPF được bật, lệnh dumpsys netd trafficcontroller
sẽ hiển thị nội dung chi tiết của từng bản đồ eBPF, bao gồm cả thông tin về ổ cắm được gắn thẻ, số liệu thống kê theo thẻ, UID và giao diện người dùng, cũng như thông tin trùng khớp với UID của chủ sở hữu.
Vị trí kiểm thử
Các bài kiểm tra CTS được đặt tại:
- https://android.googlesource.com/platform/cts/+/main/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
- https://android.googlesource.com/platform/cts/+/main/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
- https://android.googlesource.com/platform/system/netd/+/main/tests/bpf_base_test.cpp
Các bài kiểm thử VTS nằm tại https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.
Các bài kiểm thử đơn vị nằm ở: