เครื่องมือการรับส่งข้อมูลเครือข่าย eBPF ใช้การติดตั้งใช้งานร่วมกันของเคอร์เนลและพื้นที่ผู้ใช้
เพื่อตรวจสอบการใช้เครือข่ายในอุปกรณ์นับตั้งแต่การบูตอุปกรณ์ครั้งล่าสุด
โดยมีฟังก์ชันเพิ่มเติม เช่น การติดแท็กซ็อกเก็ต การแยกการเข้าชมใน
เบื้องหน้า/เบื้องหลัง และไฟร์วอลล์ต่อ UID เพื่อบล็อกแอปจากการเข้าถึงเครือข่าย
โดยขึ้นอยู่กับสถานะของโทรศัพท์ สถิติที่รวบรวมจากเครื่องมือจะจัดเก็บไว้ในโครงสร้างข้อมูลเคอร์เนลที่เรียกว่า eBPF maps
และบริการต่างๆ เช่น NetworkStatsService
จะใช้ผลลัพธ์เพื่อแสดงสถิติการเข้าชมแบบถาวรตั้งแต่การบูตครั้งล่าสุด
ตัวอย่างและแหล่งที่มา
การเปลี่ยนแปลงใน Userspace ส่วนใหญ่จะอยู่ในโปรเจ็กต์ system/netd
และ framework/base
การพัฒนาจะดำเนินการใน AOSP ดังนั้นโค้ด AOSP จะเป็นเวอร์ชันล่าสุดอยู่เสมอ
แหล่งข้อมูลส่วนใหญ่อยู่ที่
system/netd/server/TrafficController*
system/netd/bpfloader
และ
system/netd/libbpf/
นอกจากนี้ framework/base/
และ system/core
ยังมีการเปลี่ยนแปลงเฟรมเวิร์กที่จำเป็นบางอย่างด้วย
การใช้งาน
ตั้งแต่ Android 9 เป็นต้นไป อุปกรณ์ Android ที่ใช้
เคอร์เนล 4.9 ขึ้นไปและจัดส่งพร้อมกับรุ่น P ตั้งแต่แรกต้องใช้
การบัญชีการตรวจสอบการรับส่งข้อมูลเครือข่ายที่อิงตาม eBPF แทน xt_qtaguid
โครงสร้างพื้นฐานใหม่มีความยืดหยุ่นและบำรุงรักษาได้มากกว่า และไม่จำเป็นต้องใช้
โค้ดเคอร์เนลนอกทรี
ความแตกต่างด้านการออกแบบที่สำคัญระหว่างการตรวจสอบการรับส่งข้อมูลแบบเดิมกับ eBPF แสดงอยู่ในรูปที่ 1
รูปที่ 1 ความแตกต่างของการออกแบบการตรวจสอบการรับส่งข้อมูลเดิม (ซ้าย) และ eBPF (ขวา)
trafficController
การออกแบบใหม่cgroup
ยังอิงตามตัวกรอง eBPF ต่อcgroup
รวมถึงxt_bpf
โมดูล netfilter ภายในเคอร์เนลด้วย ระบบจะใช้ตัวกรอง eBPF เหล่านี้
กับการรับ/ส่งแพ็กเก็ตเมื่อแพ็กเก็ตผ่านตัวกรอง cgroup
ตัวกรอง eBPF
อยู่ที่เลเยอร์การขนส่งและมีหน้าที่นับการรับส่งข้อมูล
เทียบกับ UID ที่ถูกต้องโดยขึ้นอยู่กับ UID ของซ็อกเก็ตและการตั้งค่าในพื้นที่ผู้ใช้
xt_bpf
netfilter เชื่อมต่ออยู่ที่bw_raw_PREROUTING
และ
bw_mangle_POSTROUTING
chain และมีหน้าที่นับการรับส่งข้อมูลเทียบกับ
อินเทอร์เฟซที่ถูกต้อง
ในเวลาบูต กระบวนการในพื้นที่ผู้ใช้ trafficController
จะสร้างแผนที่ eBPF
ที่ใช้สำหรับการเก็บรวบรวมข้อมูล และปักหมุดแผนที่ทั้งหมดเป็นไฟล์เสมือนที่ sys/fs/bpf
จากนั้นกระบวนการที่มีสิทธิ์ bpfloader
จะโหลดโปรแกรม eBPF ที่คอมไพล์ล่วงหน้าลงใน
เคอร์เนลและแนบโปรแกรมดังกล่าวกับ cgroup
ที่ถูกต้อง มีรูทเดียว
cgroup
สำหรับการเข้าชมทั้งหมด ดังนั้นกระบวนการทั้งหมดจึงควรอยู่ใน cgroup
นั้น
โดยค่าเริ่มต้น
ในเวลาที่รัน trafficController
สามารถติดแท็ก/เลิกติดแท็กซ็อกเก็ตได้โดยการเขียนไปยัง
traffic_cookie_tag_map
และ traffic_uid_counterSet_map
NetworkStatsService
อ่านข้อมูลสถิติการเข้าชมจาก
traffic_tag_stats_map
, traffic_uid_stats_map
และ traffic_iface_stats_map
ได้
นอกเหนือจากฟังก์ชันการรวบรวมสถิติการเข้าชมแล้ว ตัวกรอง trafficController
และ
cgroup
eBPF ยังมีหน้าที่บล็อกการเข้าชมจาก UID บางรายการ
โดยขึ้นอยู่กับการตั้งค่าโทรศัพท์ด้วย ฟีเจอร์การบล็อกการรับส่งข้อมูลเครือข่ายตาม UID
จะมาแทนที่xt_owner
โมดูลภายในเคอร์เนล และ
กำหนดค่าโหมดรายละเอียดได้โดยการเขียนไปยังtraffic_powersave_uid_map
traffic_standby_uid_map
และ traffic_dozable_uid_map
การใช้งานใหม่นี้เป็นไปตามการใช้งานโมดูล xt_qtaguid
เดิม ดังนั้น TrafficController
และ NetworkStatsService
จะทํางานได้ทั้งกับการใช้งานเดิมหรือการใช้งานใหม่ หากแอปใช้ API สาธารณะ แอปก็ไม่ควรได้รับผลกระทบใดๆ ไม่ว่าxt_qtaguid
หรือเครื่องมือ eBPF จะใช้ในเบื้องหลังหรือไม่ก็ตาม
หากเคอร์เนลของอุปกรณ์อิงตามเคอร์เนลทั่วไปของ Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 ขึ้นไป) คุณก็ไม่จำเป็นต้องแก้ไข HAL, ไดรเวอร์ หรือโค้ดเคอร์เนลเพื่อใช้เครื่องมือ eBPF ใหม่
ข้อกำหนด
การกำหนดค่าเคอร์เนลต้องเปิดการกำหนดค่าต่อไปนี้
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_INET_UDP_DIAG=y
การทดสอบการกำหนดค่าเคอร์เนล VTS มีประโยชน์เมื่อตรวจสอบว่าได้เปิดการกำหนดค่าที่ถูกต้องแล้ว
กระบวนการเลิกใช้งาน xt_qtaguid เดิม
เครื่องมือ eBPF ใหม่จะแทนที่xt_qtaguid
โมดูลและxt_owner
โมดูล
ที่ใช้เป็นพื้นฐาน เราจะเริ่มนำโมดูล xt_qtaguid
ออกจากเคอร์เนล Android
และปิดใช้การกำหนดค่าที่ไม่จำเป็น
ในรุ่น Android 9 xt_qtaguid
จะเปิดอยู่ในอุปกรณ์ทั้งหมด แต่ API สาธารณะทั้งหมดที่อ่านไฟล์ proc ของโมดูล xt_qtaguid
โดยตรงจะย้ายไปอยู่ในบริการ NetworkManagement
NetworkManagement
บริการจะทราบว่าเครื่องมือ eBPF เปิดอยู่หรือไม่และเลือกโมดูลที่เหมาะสมเพื่อรับสถิติการใช้งานเครือข่ายของแต่ละแอป ทั้งนี้ขึ้นอยู่กับเวอร์ชันเคอร์เนลของอุปกรณ์และ API ระดับแรก
แอปที่มี SDK ระดับ 28 ขึ้นไปจะถูกบล็อกไม่ให้เข้าถึงไฟล์ xt_qtaguid
proc โดย sepolicy
ในการเปิดตัว Android ครั้งถัดไปหลังจากเวอร์ชัน 9 เราจะบล็อกการเข้าถึงxt_qtaguid
ไฟล์ proc เหล่านั้นของแอปโดยสมบูรณ์ และจะเริ่มนำxt_qtaguid
โมดูลออกจากเคอร์เนลทั่วไปของ Android เวอร์ชันใหม่ หลังจากนำออกแล้ว เราจะอัปเดตการกำหนดค่าพื้นฐานของ Android สำหรับเคอร์เนลเวอร์ชันนั้นเพื่อปิดโมดูล xt_qtaguid
อย่างชัดเจน โมดูล xt_qtaguid
จะเลิกใช้งานโดยสมบูรณ์เมื่อข้อกำหนดเวอร์ชันเคอร์เนลขั้นต่ำสำหรับการเปิดตัว Android คือ 4.9 ขึ้นไป
ในการเปิดตัว Android 9 เฉพาะอุปกรณ์ที่เปิดตัว พร้อมกับ Android 9 เท่านั้นที่ต้องมี ฟีเจอร์ eBPF ใหม่ สำหรับอุปกรณ์ที่จัดส่งพร้อมเคอร์เนลที่รองรับเครื่องมือ eBPF เราขอแนะนำให้อัปเดตเป็นฟีเจอร์ eBPF ใหม่เมื่ออัปเกรดเป็น Android 9 ไม่มีการทดสอบ CTS เพื่อบังคับใช้ การอัปเดตนั้น
การตรวจสอบความถูกต้อง
คุณควรใช้แพตช์จากเคอร์เนลทั่วไปของ Android และ Android AOSP
main เป็นประจำ ตรวจสอบว่าการติดตั้งใช้งานผ่านการทดสอบ VTS และ CTS ที่เกี่ยวข้อง รวมถึง
netd_unit_test
และlibbpf_test
การทดสอบ
มีkernel net_tests
เพื่อให้แน่ใจว่าคุณได้เปิดใช้ฟีเจอร์ที่จำเป็นและได้ย้อนกลับแพตช์เคอร์เนลที่จำเป็น
แล้ว การทดสอบจะรวมเป็นส่วนหนึ่งของการทดสอบ VTS ใน Android 9
มี Unit Test บางรายการใน system/netd/
(netd_unit_test
และ
libbpf_test
)
และมีการทดสอบบางรายการใน netd_integration_test
เพื่อตรวจสอบลักษณะการทำงานโดยรวม
ของเครื่องมือใหม่
CTS และโปรแกรมตรวจสอบ CTS
เนื่องจาก Android 9 รองรับทั้ง 2 โมดูลการตรวจสอบการรับส่งข้อมูล จึงไม่มีการทดสอบ CTS เพื่อบังคับใช้โมดูลใหม่ในอุปกรณ์ทั้งหมด แต่สำหรับอุปกรณ์ที่มีเคอร์เนลเวอร์ชันสูงกว่า 4.9
ซึ่งจัดส่งพร้อมกับ Android 9 (เช่น
API ระดับแรก >= 28) จะมีการทดสอบ CTS ใน GSI เพื่อตรวจสอบว่า
กำหนดค่าโมดูลใหม่ถูกต้องแล้ว คุณใช้การทดสอบ CTS แบบเก่า เช่น TrafficStatsTest
,
NetworkUsageStatsTest
และ CtsNativeNetTestCases
เพื่อยืนยันลักษณะการทำงานให้สอดคล้องกับโมดูล UID แบบเก่าได้
การทดสอบด้วยตนเอง
มี Unit Test บางรายการใน system/netd/
(netd_unit_test
,
netd_integration_test
และ
libbpf_test
)
มีการรองรับ dumpsys สำหรับการตรวจสอบสถานะด้วยตนเอง คำสั่ง
dumpsys netd
แสดงสถานะพื้นฐานของโมดูล trafficController
และ
ระบุว่าเปิด eBPF อย่างถูกต้องหรือไม่ หากเปิด eBPF ไว้ คำสั่ง
dumpsys netd trafficcontroller
จะแสดงเนื้อหาโดยละเอียดของ eBPF
map แต่ละรายการ ซึ่งรวมถึงข้อมูลซ็อกเก็ตที่ติดแท็ก สถิติต่อแท็ก UID และ iface รวมถึง
การจับคู่ UID ของเจ้าของ
สถานที่ทดสอบ
การทดสอบ CTS อยู่ที่
- 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
การทดสอบ VTS อยู่ที่ https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py
การทดสอบหน่วยอยู่ที่