%20%E5%A6%82%E4%BD%95%E5%9B%9E%E8%A6%86%E6%AD%A3%E7%A2%BA%E7%9A%84%E8%A3%9D%E7%BD%AE%EF%BC%9F.png)
查看內核原始碼,我發現在處理 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)並選擇前一個傳入橋接端口作為傳出橋接端口,而不是將答案泛洪到其所有端口(因為可以找到這樣一個最近的條目):
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 的設備橋接口被橋端口覆蓋:
static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb, bool local_orig) { ... skb->dev = to->dev; ...