การตรวจสอบการเข้าชม eBPF

เครื่องมือการรับส่งข้อมูลเครือข่าย 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

ความแตกต่างในการออกแบบการตรวจสอบการรับส่งข้อมูลเดิมและ eBPF

รูปที่ 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 ใหม่

ข้อกำหนด

  1. การกำหนดค่าเคอร์เนลต้องเปิดการกำหนดค่าต่อไปนี้

    1. CONFIG_CGROUP_BPF=y
    2. CONFIG_BPF=y
    3. CONFIG_BPF_SYSCALL=y
    4. CONFIG_NETFILTER_XT_MATCH_BPF=y
    5. 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 อยู่ที่

การทดสอบ VTS อยู่ที่ https://android.googlesource.com/kernel/tests/+/android16-release/net/test/bpf_test.py

การทดสอบหน่วยอยู่ที่