星期三, 12月 10, 2014

netif_receive_skb

網路界面驅動程式使用 NAPI 的方式接收封包會呼叫 netif_receive_skb(skb),將 sk_buff 結構的封包傳給上層 (實際上是 __netif_receive_skb()):
  1. 呼叫 netpoll_rx() 來支援 Netpoll API。netpoll 在 kernel 裡實作 UDP clients 及 servers,應用在 netdump, remote syslog, netlog/netconsole, kgdb 等,即使 kernel crash 也可以送收封包。
  2. 如果有 VLAN tag,則做標記,並做 untag 動作,更新 sk_buff 相關欄位。
  3. 呼叫接收任何 Ether Type 的封包處理函數 (ptype_all 部份,用在 tcpdump 等)
  4. 呼叫 handle_ing() 作為 ingress queueing
  5. 如果原本有 VLAN tag,封包的 net_device 換成此 VLAN ,從 2 再開始。
  6. 呼叫 net_device 的 rx_handler (用於 bridged 的界面),結果可能是 
    • RX_HANDLER_CONSUMED:已經完成處理,結束。
    • RX_HANDLER_ANOTHER:從 2 再開始下一回合。
    • RX_HANDLER_EXACT:接下來需符合 sk_buff 指定的 net_device
    • RX_HANDLER_PASS:接下來可以符合不指定 net_device
  7. 呼叫特定 Ether Type 的封包處理函數:例如 VLAN 的 vlan_skb_recv()、ARP 的 arp_rcv()、IPv4 的 ip_rcv()、IPv6 的 ipv6_rcv()、PPPoE 的 pppoe_rcv() 跟 pppoe_disc_rcv() 等。

註:
  • 針對 Ether Type 的封包處理函數紀錄在 ptype_all 跟 ptype_ base[],透過 dev_add_pack() 登記 ether type 及處理的函數 (struct packet_type)相反動作是呼叫 dev_remove_pack() 來移除。
  • L2 socket 如果要收的 Ether Type 是 VLAN,應該會收不到
  • pfmemalloc 只用在 ARP, IP, VLAN 等 Ether Type,不做 任何 Ether Type 的封包處理
  • vlan_skb_recv() 移除 VLAN header 後,透過 netif_rx() 放到 input_pkt_queue,再 poll 取出呼叫 netif_receive_skb()。

參考來源:
  1. net/core/dev.c 及相關 source code
  2. http://www.linuxfoundation.org/collaborate/workgroups/networking/kernel_flow#Receive_flow
  3. http://www.cs.columbia.edu/~nahum/w6998/lectures/device-layer.ppt
延伸閱讀

沒有留言:

張貼留言