4.2 网络类:XDP与TC的性能分界


4.2 网络类:XDP 与 TC 的性能分界

本节摘要:XDP 在驱动刚收到帧、套接字缓冲区尚未分配时就能丢弃或转发;TC 工作在已有 sk_buff、能看到更多栈内元数据的位置。要线速过滤 DDoS 选前者,要按连接或 cgroup 做精细策略选后者。挂错层,不是慢一点,是对象根本不存在。

本节目标

阅读完本节,你应当能够:

  1. 在收包路径上标出 XDP、TC、套接字过滤的前后关系
  2. 说明 XDP 为什么快、以及它因此看不见什么
  3. 在“丢包/转发”与“改写/分类”之间做钩子选择
  4. 识别驱动不支持原生 XDP 时的降级含义

第 1.1 节说抓包太靠外。网络类 eBPF 把观测和干预点往左推。推多远,决定你手里拿的是原始帧还是已经长出身份的包。

一、同一条河的三个渡口

帧进网卡,DMA 写入内存。XDP 可以在驱动里最早被唤醒,此时常常还没有完整的 sk_buff。你能读包头、改部分字节、决定通过、丢弃、重定向。省下的是分配、协议解析、iptables 遍历。这就是它能在攻击流量下活下来的原因:垃圾在进城之前被扔掉,而不是进了城再安检。

TC 挂在流量控制层,包已经是 sk_buff,有设备、协议、有时还有套接字关联。你可以做分类、改字段、与 cgroup 策略配合。延迟高于 XDP,表达力也高于 XDP。服务网格把重定向放在这一带,是因为需要的不是“看见以太网帧”,而是“看见这是谁的连接”。

套接字过滤更靠后,面向已经送到某个套接字的数据。适合按连接观测,不适合挡在网卡门口。

海关有三道。第一道在港口看集装箱外观,能把整船垃圾挡回去,但看不到箱内提单属于哪个公司。第二道在保税区,单据齐了,能按公司策略开箱。第三道在收货门口,只处理已经派送到你家的货。抱怨第一道“不够智能”,是在要求港口干保税区的活。

挂载 对象在不在 能做什么 看不见什么 典型题
原生 XDP 往往还无完整 sk_buff 丢、过、重定向、有限改写 套接字、cgroup、连接跟踪细节 线速过滤、DDoS 前置
通用 XDP 有 sk_buff 回退路径 能力接近但更慢 相对原生多付一次代价 驱动不支持时的降级
TC 有 sk_buff 分类、改写、配合策略 已经付了分配成本 东西向策略、网格劫持
套接字过滤 已到套接字 按连接过滤观测 到不了这里的包 应用侧精细抓取

二、性能分界不是参数,是对象生命周期

把 XDP 程序写成“查连接表、看进程名、再决定”会让人失望:那一拍进程名往往不在。你要么把状态自己用 Map 从追踪类同步过来,要么把程序往后挪到 TC。

反过来,把本该在 XDP 丢掉的攻击包留到 TC,等于让分配器和协议栈给攻击者打工。CPU 在构造 sk_buff 上烧完,你的精细策略没有机会表现。

所以分界问题应这样问:决策所需的最晚对象,最早在哪一拍出现? 只需要五元组,XDP 够。需要“这个包属于哪个 Pod 的哪条已建立连接”,往 TC 或 sockops 走,并用 Map 把前面的计数接上。

/* 概念性:XDP 只根据包头做丢或过 */ SEC("xdp") int filter(struct xdp_md *ctx) { if (is_syn_flood_tuple(ctx)) return XDP_DROP; return XDP_PASS; }

⚠️ 常见坑:在不支持原生 XDP 的网卡上以为自己已经“线速”。通用 XDP 仍会走分配路径,数字会好看过 TC,但远不是驱动内那一档。
💡 关键直觉:先列出决策依赖的字段,再选渡口。字段不在那一拍,快没有意义。

三、工程要点:卸载、多口、与 iptables 共存

网卡硬件卸载能把 XDP 程序放到 ASIC 上。这是真正的零主机 CPU,限制也更死:Helper 更少,调试更难。不要假设开发机的 XDP 语义等于卸载后的语义。

多网卡、多队列时,程序要无状态或 Map 自己分片。按 CPU 的计数还好说,按连接的状态机要考虑包打在不同队列。

与 iptables/nftables 共存时,明确谁先动手。XDP 丢了的包,后面规则看不见,排障会误判“规则没生效”。把 eBPF 策略和传统规则的责任写进同一张图,比再加一层“全镜像抓包”更有用。

Cilium 一类平台把大量 TC/XDP 程序当成数据平面。你在节点上手动挂一条 XDP 可能和它们抢挂钩点。生产上优先走平台提供的挂载,而不是 SSH 上去“先试一下”。

图:收包路径上对象逐渐长出来

图:收包路径上对象逐渐长出来

问题:XDP 能不能做 TLS 卸载或七层路由?

原生 XDP 看得到的是还没走到应用的字节。做完整七层要自己解析,复杂度和验证压力都高。多数七层策略放用户态或更靠后的钩子,XDP 只做明显的四层垃圾。

问题:egress 为什么很少谈 XDP?

XDP 主要设计在收路径的最早点。出方向更常见的是 TC。出方向的“早”和入方向的“早”不是同一个驱动回调。

四、DDoS 与网格策略为什么不该写成同一个程序

攻击流量和东西向业务流量的决策对象不同。攻击要在最早的渡口用最少字段丢掉;网格要在身份齐全的地方做重定向和策略。塞进同一个程序,验证器路径会膨胀,XDP 的热路径会被策略树拖死,TC 又挡不住线速洪水。拆开之后用 Map 共享“这五元组已识别为攻击”之类的小键即可,不必共享整份策略。

压测方法也不同。测 XDP 要用能打满网卡队列的发包器,看 CPU 是否仍接近空闲、看驱动是否走原生路径。测 TC 要用真实连接与 cgroup,看策略命中和错误重定向。用 TC 压测的数字去宣传 XDP 能力,或反过来,都会在真实攻击里穿帮。

多队列 RSS 会把同一连接的包打到不同 CPU。XDP 程序若在每 CPU 上维护未同步的限速桶,攻击者很容易把桶稀释。限速状态要么用全局原子并接受争用,要么按对称哈希保证同连接同 CPU。设计限速时把 RSS 写进假设,不要当实验机单队列的结论。

IPv6 扩展头、VLAN 叠层、封装协议会让“只读固定偏移的以太网+IP+TCP”失效。XDP 里解析要有界,超预算就交给后面的栈或丢掉。不要为了完整性在最早渡口写深度解析器。那是把 TC 甚至用户态的活抢到了最贵的地方。

和主机防火墙的责任表必须公开:哪类丢包发生在 XDP,哪类发生在 nftables,哪类发生在应用。排障时按表看计数。没有表时,每个人都会说“我这边放行了”,包却已经在更早的渡口消失。

现场笔记:通用 XDP 被当成线速

网卡不支持原生路径,程序走了通用 XDP。压测数字好过 TC,于是对外宣称线速过滤。真攻击来时 CPU 照样打满,因为 sk_buff 仍在分配。后来在指标里显式标出驱动模式:原生、通用、卸载。模式不对,数字不许写进容量规划。宣传和路径必须同一张图。

RSS 把同连接打到多核,每 CPU 限速桶被稀释,攻击从所有队列进来,每个桶都觉得自己没满。改成按对称哈希保证同连接同核,或用全局原子并接受争用。设计假设里写明队列模型,实验机单队列的结论禁止直接上线。

和 nftables 的责任表没公开时,XDP 丢了的包在防火墙计数里消失,两边互相说放行了。公开责任表之后,排障先看哪一层的计数在涨。没有表,会议会变成信仰之争。有表,会议会变成读数。读数更快。

延伸讨论:路径模式必须写进容量数字旁边

指标标明原生、通用还是卸载。模式不对,数字不许进容量规划。通用路径上的好看数字,挡不住真攻击时的分配成本。RSS 下每 CPU 限速桶会被稀释,同连接要能落到可同步的状态,或接受全局原子争用。假设里写队列模型,单队列实验机结论禁止直接上线。和主机防火墙的责任表公开:谁先丢,谁的计数该涨。没有表,会议变成信仰。有表,会议变成读数。IPv6 扩展头和封装让固定偏移失效,XDP 解析必须有界,超预算交给后面或丢掉。最早渡口不写深度解析器。深度是贵的,贵要花在对象已经长全的地方。对象还没长全时,贵等于把自己变成攻击者的帮凶,帮他消耗你的 CPU。帮凶角色要拒绝。

对照清单

  1. 决策所需最晚对象最早在哪一拍出现,只需要五元组才配用 XDP。
  2. 原生、通用、卸载三种模式必须标在指标旁,模式不对数字不许进规划。
  3. DDoS 过滤和网格策略不要写成同一个程序,用小键共享识别结果即可。
  4. RSS 会稀释每 CPU 限速桶,同连接要能落到可同步状态。
  5. XDP 丢了的包 iptables 看不见,责任表不公开就会互相说放行了。
  6. 通用 XDP 仍走分配,不能拿它的数字当线速能力对外宣传。
  7. 出方向常见是 TC,不要用入方向的早去要求出方向同样早。
  8. 七层完整解析不该放在最早渡口,复杂度和验证压力都会爆。
  9. 与平台数据平面协调挂钩,手工抢 XDP 可能把策略打瞎。
  10. 压测 XDP 要用能打满队列的流量,压测 TC 要用真实连接与 cgroup。
  11. 扩展头解析必须有界,超预算丢掉或走慢路径,完整性不是最早渡口的目标。
  12. 正确的 XDP 过滤应让 CPU 下降,上升则挂错层或解析过重。

网络钩子选错,不是慢一点的问题,是你手里拿着的对象根本不是你以为的那个。在还没有套接字的地方问这是谁的 Pod,答案只能是未知或谎言。未知可以接受。谎言会变成错误策略。错误策略比慢更伤。所以把字段清单写在挂钩点前面:我要哪些字段,这些字段最早在哪一拍出现。清单会自然把人推向 XDP 或 TC。不写清单的人会被听说很快推着走。听说很快的人,常常站在通用路径上还以为自己在驱动里。

\n\n## 课堂补充\n\n字段清单决定渡口,听说很快不决定。原生通用卸载三种模式要标出来。垃圾在进城前扔掉。身份在保税区才齐全。RSS会稀释每核桶。责任表不公开就会信仰之争。七层别抢最早渡口。出方向常见是TC。平台挂钩是主权。压测方法按层选。扩展头有界。CPU该降不降就是挂错层。\n\n## 本章回顾

  • XDP 快是因为对象还没长全,所以也看不见连接身份。
  • TC 在 sk_buff 之后,适合策略与网格,不适合挡线速洪水。
  • 按决策所需字段选渡口,不要按“听说 XDP 快”选。
  • 通用 XDP 是降级,不要拿它的数字当原生能力。
  • 与平台数据平面协调挂钩点,避免手工抢挂。
  • 谁先丢包谁负责可见性:XDP 丢了的,iptables 帮不了你解释。

下一节离开包路径,看 cgroup、LSM 和调度:策略按谁生效,安全在哪一拍裁决。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U