arp_process() 如何回复正确的设备?

arp_process() 如何回复正确的设备?

查看内核源代码,我发现在处理 ARP 请求时,net_device会直接从 中检索skb,然后似乎将回复发送到该设备(arp.c#L679):

static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{
     struct net_device *dev = skb->dev;
     ...
     arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
           sip, dev, tip, sha,
           dev->dev_addr, sha,
           reply_dst);
}

但是如果数据包通过了桥接器,那么skb就得到了它的设备用桥接设备覆盖:

static int br_pass_frame_up(struct sk_buff *skb)
{
    ...
    skb->dev = brdev;
    ...
}

难道不应该如何检索原始设备并将回复发送到那里吗?

答案1

如果帧从桥接端口到达,则意味着现在有一个新桥 FDB 条目指示在向此 MAC 地址发送帧时使用同一网桥端口:回复将发送到查询到达的同一网桥端口。

因此,从 ARP 层的角度来看,数据包在桥接接口上被接收,并且应答也在桥接接口上发回。

当回复到达下层:桥接器时,桥接器代码会在其转发数据库(又名FIB)并选择前一个传入桥接端口作为传出桥接端口,而不是将答案泛洪到其所有端口(因为可以找到这样一个最近的条目):

br_device.c:

netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
...
  } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
      br_forward(dst->dst, skb, false, true);
  } else {
      br_flood(br, skb, BR_PKT_UNICAST, false, true);

与之前相反,skb 的设备桥接口被桥端口覆盖:

br_forward.c:

static void __br_forward(const struct net_bridge_port *to,
           struct sk_buff *skb, bool local_orig)
{
...
      skb->dev = to->dev;
...

相关内容