Linux协议栈(7)——网络层实现
網絡層具體就是IP協議層,處理發送和接收數據外,還需要進行轉發和路由分組。在查找最佳路由并選擇適當網卡的時候也會涉及對底層地址族的處理,例如MAC地址。
ip頭數據結構定義在:include/uapi/linux/ip.h。
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
??? ????__u8??? ihl:4,
??????????????? version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
??????? __u8??? version:4,
??????????????? ihl:4;
#else
#error? "Please fix <asm/byteorder.h>"
#endif
??????? __u8??? tos;
??????? __be16? tot_len;
??????? __be16? id;
??? ????__be16? frag_off;
??????? __u8??? ttl;
??????? __u8??? protocol;
??????? __sum16 check;
??????? __be32? saddr;
??????? __be32? daddr;
??????? /*The options start here. */
};
1.1.1.1? 接收
??????????? ipv4數據包的主接收方法是ip_rcv()函數,會檢測報到類似如果是PACKET_OTHERHOST(定義在include/uapi/linux/if_packet.h文件中)則直接丟棄。檢查是否是共享的包,如果是分享的包則克隆它。獲取ip頭數據結構,來操作相關協議事務。然后調用NK_HOOK,NF_HOOK定義在include/linux/netfilter.h文件中。
static inline int
NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb,
??????? struct net_device *in, struct net_device *out,
??????? int (*okfn)(struct net *, struct sock *, struct sk_buff *))
??????????? 它是netfilter鉤子函數,如果允許包傳遞則返回1。如果返回其他值說明這個包被hook給消耗掉了。
??????????? 其中hook為NF_INET_PRE_ROUTING(定義在
include/uapi/linux/netfilter.h)
okfn指向ip_rcv_finish()函數。ip_rcv_finish()也定義在:net/ipv4/ip_input.c
??????????? 在ip網絡層中需要分段、重組的實現。須在路由選在子系統中查找,確定是發給當前主機還是轉發。
??????????? 如果是當前主機則依次調用方法ip_local_deliver()和ip_local_deliver_finish()函數。如果需要轉發則調用ip_forward()函數。
1.1.1.1.1????????? 分片合并
IP分組可能是分片的,可以通過ip_defrag重新組合分片分組的各個部分。代碼流程如下圖(圖摘自《深入linux內核架構》):
??????????? 內核在獨立的緩存中管理原本屬于一個分組的各個分片,該緩存稱為分片緩存(fragment cache)。屬于同一個分組的各個分片保存在一個獨立的等待隊列中,直至該分組的所有分片到達。
??????????? ip_frag_reasm將各個分片重新組合起來。
1.1.1.1.2????????? 交付到傳輸層
如果數據是給本機的,那么返回到ip_local_deliver。調用netfilter掛鉤NF_IP_LOCAL_IN恢復在ip_local_deliver_finish函數中的處理。
??????????? 分組的協議標識符確定一個傳輸層的函數,分組將傳遞給該函數。每個協議都有一個net_protocol結構的實例。定義在:
include/net/protocol.h文件中
struct net_protocol {???
??????? int???????????????????? (*early_demux)(struct sk_buff *skb);
??????? int???????????????????? (*early_demux_handler)(struct sk_buff *skb);
??????? int???????????????????? (*handler)(struct sk_buff *skb);
??????? void??????????????????? (*err_handler)(struct sk_buff *skb, u32 info);?????????????????????????????????????
??????? unsigned int??????????? no_policy:1,?????????????
? ??????????????????????????????netns_ok:1,??????????????
??????????????????????????????? /* does the protocol do more stringent
???????????????????????????????? * icmp tag validation than simple
???????????????????????????????? * socket lookup?
?????????? ??????????????????????*/??????????????????????
??????????????????????????????? icmp_strict_tag_validation:1;??????????????????????????????????????????????????????
};
1.1.1.1.3????????? 分組轉發
ip分組也可能轉發到另一臺計算機。這就需要調用ip_forward函數。
??????????? ip_forward使用NF_HOOK掛鉤函數,掛鉤編號為NF_INET_FORWARD,回調函數為ip_forward_finish。
1.1.1.2? 發送
由ip_queue_xmit函數將數據包從L4移到L3
網絡層要選擇合適的網間路由和交換結點,確保數據及時傳送。其主要任務包括 (1)路由處理,即選擇下一跳 (2)添加 IP header(3)計算 IP header checksum,用于檢測 IP 報文頭部在傳播過程中是否出錯 (4)可能的話,進行 IP 分片(5)處理完畢,獲取下一跳的 MAC 地址,設置鏈路層報文頭,然后轉入鏈路層處理。
??????????? 發送和接收操作的流程并不總是分離的,如果分組只通過當前計算機轉發,那么發送和接收操作是交織的。總結
以上是生活随笔為你收集整理的Linux协议栈(7)——网络层实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js中如何优雅的解析数据
- 下一篇: linux 其他常用命令