linux vrf icmp reply /vrf icmp 响应错误消息
static inline void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
{
__icmp_send(skb_in, type, code, info, IPCB(skb_in));
}
static inline void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
{
__icmp_send(skb_in, type, code, info, IPCB(skb_in));
}
内核协议栈中:
ip_rcv_core IPCB(skb)->iif = skb->skb_iif; vrf_ip_rcv skb->dev = vrf_dev; skb->skb_iif = vrf_dev->ifindex; IPCB(skb)->flags |= IPSKB_L3SLAVE;
-
保存现场: 当数据包刚被网卡接收时,
ip_rcv_core会立即把当前的入接口索引(skb->skb_iif)备份到控制块(IPCB(skb)->iif)中。 -
VRF 干扰: 随后,如果配置了 VRF,VRF 驱动(
drivers/net/vrf.c)会接管数据包,并修改skb->skb_iif为 VRF 虚拟设备的索引。 -
恢复现场: 当需要发送 ICMP 错误消息时(比如在
icmp.c中),skb->skb_iif已经被改写了,不再是物理接口。这时,代码就会去读之前备份在parm->iif中的原始值,从而向正确的接口报告错误。
当内核生成 ICMP 错误消息时,它去读 skb->skb_iif,读到的是 VRF 设备。结果就是,ICMP 消息的源 IP 变成了 VRF 设备的 IP(或者 VRF 下其他端口的 IP),而不是真正接收数据包的物理接口 IP。
运行 traceroute 时,显示的路径节点 IP 是错的
bugfix:
-
核心逻辑: 不要直接读取已经被 VRF 修改过的
skb->skb_iif。 -
新方法: 改为读取**控制块(Control Block)**中的
iif字段。

traceroute 的核心就是依赖设备返回:
ICMP Time Exceeded
而返回 ICMP 时内核必须要构造 ICMP 包 → 就会执行这段代码。
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子

浙公网安备 33010602011771号