Devlink 陷阱¶
背景¶
能够卸载内核数据路径并执行桥接和路由等功能的设备,也必须能够将特定数据包发送到内核(即 CPU)进行处理。
例如,一个充当多播感知桥的设备必须能够将 IGMP 组成员报告发送到内核,以便桥模块处理。如果不处理此类数据包,桥模块将永远无法填充其 MDB。
再举一个例子,考虑一个充当路由器并收到 TTL 为 1 的 IP 数据包的设备。在路由该数据包时,设备必须将其发送到内核,以便内核也能路由它并生成一个 ICMP 超时错误数据报。如果不让内核自己路由此类数据包,traceroute
等工具将无法工作。
将某些数据包发送到内核进行处理的基本能力称为“数据包陷阱”。
概述¶
devlink-trap
机制允许有能力的设备驱动程序向 devlink
注册其支持的数据包陷阱,并将陷阱数据包报告给 devlink
以进行进一步分析。
收到陷阱数据包后,devlink
将执行每个陷阱的数据包和字节计数,并可能通过 netlink 事件将数据包报告给用户空间,同时提供所有元数据(例如,陷阱原因、时间戳、输入端口)。这对于丢弃陷阱(参见陷阱类型)特别有用,因为它允许用户进一步了解否则不可见的数据包丢弃。
下图提供了 devlink-trap
的一般概述
Netlink event: Packet w/ metadata
Or a summary of recent drops
^
|
Userspace |
+---------------------------------------------------+
Kernel |
|
+-------+--------+
| |
| drop_monitor |
| |
+-------^--------+
|
| Non-control traps
|
+----+----+
| | Kernel's Rx path
| devlink | (non-drop traps)
| |
+----^----+ ^
| |
+-----------+
|
+-------+-------+
| |
| Device driver |
| |
+-------^-------+
Kernel |
+---------------------------------------------------+
Hardware |
| Trapped packet
|
+--+---+
| |
| ASIC |
| |
+------+
陷阱类型¶
devlink-trap
机制支持以下数据包陷阱类型
drop
:陷阱数据包被底层设备丢弃。数据包仅由devlink
处理,而不注入到内核的 Rx 路径。陷阱动作(参见陷阱动作)可以更改。
exception
:陷阱数据包因异常(例如,TTL 错误,缺少邻居条目)而未按底层设备预期转发,并被捕获到控制平面进行解析。数据包由devlink
处理并注入到内核的 Rx 路径。不允许更改此类陷阱的动作,因为它很容易破坏控制平面。
control
:陷阱数据包被设备捕获,因为这些是控制数据包,是控制平面正常运行所必需的。例如,ARP 请求和 IGMP 查询数据包。数据包注入到内核的 Rx 路径,但不报告给内核的丢弃监视器。不允许更改此类陷阱的动作,因为它很容易破坏控制平面。
陷阱动作¶
devlink-trap
机制支持以下数据包陷阱动作
trap
:数据包的唯一副本发送到 CPU。
drop
:数据包被底层设备丢弃,不发送副本到 CPU。
mirror
:数据包被底层设备转发,并将副本发送到 CPU。
通用数据包陷阱¶
通用数据包陷阱用于描述捕获定义明确的数据包或由于定义明确的条件(例如,TTL 错误)而捕获的数据包。此类陷阱可以由多个设备驱动程序共享,其描述必须添加到下表
名称 |
类型 |
描述 |
|
|
捕获设备因多播源 MAC 而决定丢弃的入站数据包 |
|
|
捕获设备在 VLAN 标签不匹配时决定丢弃的入站数据包:入口桥接端口未配置 PVID 且数据包未标记或优先级标记 |
|
|
捕获设备决定丢弃的入站数据包,如果它们被标记了未在入口桥接端口上配置的 VLAN |
|
|
捕获设备决定丢弃的入站数据包,如果入口桥接端口的 STP 状态不是“转发” |
|
|
捕获设备决定丢弃的数据包,如果它们需要泛洪(例如,未知单播,未注册多播)且没有端口可以泛洪这些数据包 |
|
|
捕获设备决定丢弃的数据包,如果在第 2 层转发后,唯一应该传输这些数据包的端口是接收它们的端口 |
|
|
捕获设备决定丢弃的数据包,如果它们命中了黑洞路由 |
|
|
捕获设备应转发的单播数据包,其 TTL 已递减到 0 或更小 |
|
|
捕获设备决定丢弃的数据包,因为它们无法排入已满的传输队列 |
|
|
捕获设备决定丢弃的数据包,因为它们需要进行第 3 层查找,但不是 IP 或 MPLS 数据包 |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且具有单播目的 IP 和多播目的 MAC |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且其目的 IP 是环回地址(即,127.0.0.0/8 和 ::1/128) |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且其源 IP 是多播(即,224.0.0.0/8 和 ff::/8) |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且其源 IP 是环回地址(即,127.0.0.0/8 和 ::1/128) |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且其 IP 头部已损坏:错误的校验和、错误的 IP 版本或过短的 Internet 头部长度 (IHL) |
|
|
捕获设备决定丢弃的数据包,因为它们需要路由且其源 IP 是受限广播(即,255.255.255.255/32) |
|
|
捕获设备决定丢弃的 IPv6 数据包,因为它们需要路由且其 IPv6 多播目的 IP 具有保留范围(即,ffx0::/16) |
|
|
捕获设备决定丢弃的 IPv6 数据包,因为它们需要路由且其 IPv6 多播目的 IP 具有接口本地范围(即,ffx1::/16) |
|
|
捕获设备应路由但大于出口接口 MTU 的数据包 |
|
|
捕获路由后没有匹配 IP 邻居的数据包 |
|
|
捕获在多播路由期间未能通过反向路径转发 (RPF) 检查的多播 IP 数据包 |
|
|
捕获命中断开路由(即,“不可达”,“禁止”)的数据包 |
|
|
捕获未匹配任何路由的单播 IPv4 数据包 |
|
|
捕获未匹配任何路由的单播 IPv6 数据包 |
|
|
捕获设备决定丢弃的数据包,因为它们不应该被路由。例如,IGMP 查询可以由设备在第 2 层泛洪并到达路由器。此类数据包不应被路由,而应被丢弃 |
|
|
捕获设备因解封装失败(例如,数据包过短,VXLAN 头部中的保留位设置)而决定丢弃的 NVE 和 IPinIP 数据包 |
|
|
捕获设备因其覆盖源 MAC 是多播而决定丢弃的 NVE 数据包 |
|
|
捕获在处理入口流动作丢弃期间丢弃的数据包 |
|
|
捕获在处理出口流动作丢弃期间丢弃的数据包 |
|
|
捕获 STP 数据包 |
|
|
捕获 LACP 数据包 |
|
|
捕获 LLDP 数据包 |
|
|
捕获 IGMP 组成员查询数据包 |
|
|
捕获 IGMP 版本 1 组成员报告数据包 |
|
|
捕获 IGMP 版本 2 组成员报告数据包 |
|
|
捕获 IGMP 版本 3 组成员报告数据包 |
|
|
捕获 IGMP 版本 2 离开组数据包 |
|
|
捕获 MLD 多播监听器查询数据包 |
|
|
捕获 MLD 版本 1 多播监听器报告数据包 |
|
|
捕获 MLD 版本 2 多播监听器报告数据包 |
|
|
捕获 MLD 版本 1 多播监听器完成数据包 |
|
|
捕获 IPv4 DHCP 数据包 |
|
|
捕获 IPv6 DHCP 数据包 |
|
|
捕获 ARP 请求数据包 |
|
|
捕获 ARP 响应数据包 |
|
|
捕获已解封装的到达覆盖网络的 NVE ARP 数据包。例如,当需要解析的地址是本地地址时,这是必需的 |
|
|
捕获 IPv6 邻居请求数据包 |
|
|
捕获 IPv6 邻居通告数据包 |
|
|
捕获 IPv4 BFD 数据包 |
|
|
捕获 IPv6 BFD 数据包 |
|
|
捕获 IPv4 OSPF 数据包 |
|
|
捕获 IPv6 OSPF 数据包 |
|
|
捕获 IPv4 BGP 数据包 |
|
|
捕获 IPv6 BGP 数据包 |
|
|
捕获 IPv4 VRRP 数据包 |
|
|
捕获 IPv6 VRRP 数据包 |
|
|
捕获 IPv4 PIM 数据包 |
|
|
捕获 IPv6 PIM 数据包 |
|
|
捕获需要通过其接收的相同第 3 层接口路由的单播数据包。此类数据包由内核路由,但也可能导致内核生成 ICMP 重定向数据包 |
|
|
捕获命中文地路由并需要本地交付的单播数据包 |
|
|
捕获应通过不属于同一设备(例如,交换 ASIC)的外部接口(例如,管理接口)路由的数据包,如同入口接口一样 |
|
|
捕获需要路由且目的 IP 地址具有链路本地范围(即,fe80::/10)的单播 IPv6 数据包。该陷阱允许设备驱动程序避免编程链路本地路由,但仍接收用于本地交付的数据包 |
|
|
捕获目的 IP 地址是“所有节点地址”(即,ff02::1)的 IPv6 数据包 |
|
|
捕获目的 IP 地址是“所有路由器地址”(即,ff02::2)的 IPv6 数据包 |
|
|
捕获 IPv6 路由器请求数据包 |
|
|
捕获 IPv6 路由器通告数据包 |
|
|
捕获 IPv6 重定向消息数据包 |
|
|
捕获需要路由且包含路由器警报选项的 IPv4 数据包。此类数据包需要本地交付给设置了 IP_ROUTER_ALERT 套接字选项的原始套接字 |
|
|
捕获需要路由且在其逐跳扩展头部中包含路由器警报选项的 IPv6 数据包。此类数据包需要本地交付给设置了 IPV6_ROUTER_ALERT 套接字选项的原始套接字 |
|
|
捕获 PTP 时间关键事件消息(Sync, Delay_req, Pdelay_Req 和 Pdelay_Resp) |
|
|
捕获 PTP 一般消息(Announce, Follow_Up, Delay_Resp, Pdelay_Resp_Follow_Up, management 和 signaling) |
|
|
捕获在处理流动作采样期间采样的数据包(例如,通过 tc 的采样动作) |
|
|
捕获在处理流动作陷阱期间记录的数据包(例如,通过 tc 的陷阱动作) |
|
|
捕获因 RED (Random Early Detection) 算法而丢弃的数据包(即,早期丢弃) |
|
|
捕获因 VXLAN 头部解析错误而丢弃的数据包,这可能是由于数据包截断或 I 标志未设置。 |
|
|
捕获因 LLC+SNAP 头部解析错误而丢弃的数据包 |
|
|
捕获因 VLAN 头部解析错误而丢弃的数据包。可能包括意外的数据包截断。 |
|
|
捕获因 PPPoE+PPP 头部解析错误而丢弃的数据包。这可能包括会话 ID 为 0xFFFF(保留且不可用)、PPPoE 长度大于接收帧长度或此类头部上的任何常见错误 |
|
|
捕获因 MPLS 头部解析错误而丢弃的数据包,可能包括意外的头部截断 |
|
|
捕获因 ARP 头部解析错误而丢弃的数据包 |
|
|
捕获因第一个 IP 头部解析错误而丢弃的数据包。此数据包陷阱可能包括未通过 IP 校验和检查、头部长度检查(至少 20 字节)、可能因数据包截断而导致总长度字段超出接收数据包长度等的数据包 |
|
|
捕获因解析最后一个 IP 头部(IP over IP 隧道中的内部头部)错误而丢弃的数据包。此处执行与 ip_1_parsing 陷阱相同的常见错误检查 |
|
|
捕获因 GRE 头部解析错误而丢弃的数据包 |
|
|
捕获因 UDP 头部解析错误而丢弃的数据包。此数据包陷阱可能包括校验和错误、检测到不正确的 UDP 长度(小于 8 字节)或检测到头部截断。 |
|
|
捕获因 TCP 头部解析错误而丢弃的数据包。这可能包括 TCP 校验和错误、SYN、FIN 和/或 RESET 的不当组合等。 |
|
|
捕获因 IPSEC 头部解析错误而丢弃的数据包 |
|
|
捕获因 SCTP 头部解析错误而丢弃的数据包。这意味着使用了端口号 0 或头部被截断。 |
|
|
捕获因 DCCP 头部解析错误而丢弃的数据包 |
|
|
捕获因 GTP 头部解析错误而丢弃的数据包 |
|
|
捕获因 ESP 头部解析错误而丢弃的数据包 |
|
|
捕获设备因其命中黑洞下一跳而决定丢弃的数据包 |
|
|
捕获设备决定丢弃的入站数据包,因为目的 MAC 未在 MAC 表中配置且接口不在混杂模式 |
|
|
捕获 IEEE 802.1X 中指定的“可扩展认证协议局域网”(EAPOL)数据包 |
|
|
捕获设备决定丢弃的数据包,因为它们未能通过锁定桥接端口检查。即,通过锁定端口接收且其 {SMAC, VID} 不对应指向该端口的 FDB 条目的数据包 |
驱动程序特定数据包陷阱¶
设备驱动程序可以注册驱动程序特定数据包陷阱,但这些必须清晰地记录。此类陷阱可能对应于设备特定异常,并有助于调试由这些异常引起的数据包丢弃。以下列表包含指向各种设备驱动程序注册的驱动程序特定陷阱描述的链接
通用数据包陷阱组¶
通用数据包陷阱组用于聚合逻辑相关的数据包陷阱。这些组允许用户批量操作,例如设置所有成员陷阱的陷阱动作。此外,如果每个陷阱的统计信息过于狭窄,devlink-trap
可以报告每个组的聚合数据包和字节统计信息。这些组的描述必须添加到下表
名称 |
描述 |
|
包含设备在第 2 层转发(即桥接)期间丢弃的数据包陷阱 |
|
包含设备在第 3 层转发期间丢弃的数据包陷阱 |
|
包含设备在第 3 层转发期间发生异常(例如,TTL 错误)的数据包陷阱 |
|
包含设备因入队决策而丢弃的数据包陷阱 |
|
包含设备在隧道封装/解封装期间丢弃的数据包陷阱 |
|
包含设备在 ACL 处理期间丢弃的数据包陷阱 |
|
包含 STP 数据包陷阱 |
|
包含 LACP 数据包陷阱 |
|
包含 LLDP 数据包陷阱 |
|
包含多播侦听所需的 IGMP 和 MLD 数据包陷阱 |
|
包含 DHCP 数据包陷阱 |
|
包含邻居发现数据包(例如,ARP,IPv6 ND)陷阱 |
|
包含 BFD 数据包陷阱 |
|
包含 OSPF 数据包陷阱 |
|
包含 BGP 数据包陷阱 |
|
包含 VRRP 数据包陷阱 |
|
包含 PIM 数据包陷阱 |
|
包含单播环回数据包陷阱(即, |
|
包含路由后应本地交付,但不匹配更具体数据包陷阱(例如, |
|
包含应通过不属于同一设备(例如,交换 ASIC)的外部接口(例如,管理接口)路由的数据包陷阱,如同入口接口一样 |
|
包含各种 IPv6 控制数据包(例如,路由器通告)的陷阱 |
|
包含 PTP 时间关键事件消息(Sync, Delay_req, Pdelay_Req 和 Pdelay_Resp)的陷阱 |
|
包含 PTP 一般消息(Announce, Follow_Up, Delay_Resp, Pdelay_Resp_Follow_Up, management 和 signaling)的陷阱 |
|
包含设备在 ACL 处理期间采样的数据包陷阱 |
|
包含设备在 ACL 处理期间捕获(记录)的数据包陷阱 |
|
包含设备在解析期间标记为错误的数据包陷阱 |
|
包含 IEEE 802.1X 中指定的“可扩展认证协议局域网”(EAPOL)数据包的陷阱 |
数据包陷阱限速器¶
如前所述,底层设备可以将某些数据包捕获到 CPU 进行处理。在大多数情况下,底层设备能够处理的数据包速率比 CPU 能够处理的速率高出几个数量级。
因此,为了防止底层设备使 CPU 过载,设备通常包含数据包陷阱限速器,能够将捕获的数据包限制在 CPU 可以处理的速率。
devlink-trap
机制允许有能力的设备驱动程序向 devlink
注册其支持的数据包陷阱限速器。设备驱动程序可以在其初始化期间选择将这些限速器与支持的数据包陷阱组(参见通用数据包陷阱组)关联起来,从而向用户空间公开其默认控制平面策略。
设备驱动程序应通过实现相关的回调,允许用户空间更改限速器的参数(例如,速率,突发大小)以及限速器与陷阱组之间的关联。
如果可能,设备驱动程序应实现一个回调,允许用户空间检索因违反配置策略而被限速器丢弃的数据包数量。
测试¶
有关核心基础设施的测试,请参见 tools/testing/selftests/drivers/net/netdevsim/devlink_trap.sh
。应为任何新功能添加测试用例。
设备驱动程序应将其测试重点放在设备特定功能上,例如支持的数据包陷阱的触发。