Linux

arp_process() 如何回復正確的設備?

  • June 14, 2021

查看核心原始碼,我看到在處理 ARP 請求,直接net_deviceskb

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;
   ...
}

不應該是如何檢索原始設備並在那裡發送回复嗎?

如果幀從橋接埠到達,這意味著現在有一個新的橋接 fdb 條目告訴在向此 MAC 地址發送幀時使用同一橋接埠:回復將發送到查詢到達的同一橋接埠。

所以從 ARP 層的角度來看,數據包是在網橋介面上接收的,並且應答也在網橋介面上發回。

當回復到達較低層時:bridge,即在其轉發數據庫(又名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;
...

引用自:https://unix.stackexchange.com/questions/654241