歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核--網絡內核實現分析(一)--與sk_buff有關的幾個重要的數據結構

Linux內核--網絡內核實現分析(一)--與sk_buff有關的幾個重要的數據結構

日期:2017/3/1 10:10:13   编辑:Linux內核

本文分析基於Linux Kernel 3.2.1

幾個月之前做了關於Linux內核版本1.2.13網絡棧的結構框架分析並實現了基於Netfilter的包過濾防火牆,這裡以內核3.2.1內核為例來進一步分析,更全面的分析網絡棧的結構。

更多請查看 Linux內核--網絡內核實現分析

1、先說一下sk_buff結構體

這個結構體是套接字的緩沖區,詳細記錄了一個數據包的組成,時間、網絡設備、各層的首部及首部長度和數據的首尾指針。

下面是他的定義,挺長

  1. struct sk_buff {
  2. /* These two members must be first. */
  3. struct sk_buff *next;
  4. struct sk_buff *prev;
  5. ktime_t tstamp;
  6. struct sock *sk;
  7. struct net_device *dev;
  8. /*
  9. * This is the control buffer. It is free to use for every
  10. * layer. Please put your private variables there. If you
  11. * want to keep them across layers you have to do a skb_clone()
  12. * first. This is owned by whoever has the skb queued ATM.
  13. */
  14. char cb[48] __aligned(8);
  15. unsigned long _skb_refdst;
  16. #ifdef CONFIG_XFRM
  17. struct sec_path *sp;
  18. #endif
  19. unsigned int len,
  20. data_len;
  21. __u16 mac_len,
  22. hdr_len;
  23. union {
  24. __wsum csum;
  25. struct {
  26. __u16 csum_start;
  27. __u16 csum_offset;
  28. };
  29. };
  30. __u32 priority;
  31. kmemcheck_bitfield_begin(flags1);
  32. __u8 local_df:1,
  33. cloned:1,
  34. ip_summed:2,
  35. nohdr:1,
  36. nfctinfo:3;
  37. __u8 pkt_type:3,
  38. fclone:2,
  39. ipvs_property:1,
  40. peeked:1,
  41. nf_trace:1;
  42. kmemcheck_bitfield_end(flags1);
  43. __be16 protocol;
  44. void (*destructor)(struct sk_buff *skb);
  45. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  46. struct nf_conntrack *nfct;
  47. #endif
  48. #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
  49. struct sk_buff *nfct_reasm;
  50. #endif
  51. #ifdef CONFIG_BRIDGE_NETFILTER
  52. struct nf_bridge_info *nf_bridge;
  53. #endif
  54. int skb_iif;
  55. #ifdef CONFIG_NET_SCHED
  56. __u16 tc_index; /* traffic control index */
  57. #ifdef CONFIG_NET_CLS_ACT
  58. __u16 tc_verd; /* traffic control verdict */
  59. #endif
  60. #endif
  61. __u32 rxhash;
  62. __u16 queue_mapping;
  63. kmemcheck_bitfield_begin(flags2);
  64. #ifdef CONFIG_IPV6_NDISC_NODETYPE
  65. __u8 ndisc_nodetype:2;
  66. #endif
  67. __u8 ooo_okay:1;
  68. __u8 l4_rxhash:1;
  69. kmemcheck_bitfield_end(flags2);
  70. /* 0/13 bit hole */
  71. #ifdef CONFIG_NET_DMA
  72. dma_cookie_t dma_cookie;
  73. #endif
  74. #ifdef CONFIG_NETWORK_SECMARK
  75. __u32 secmark;
  76. #endif
  77. union {
  78. __u32 mark;
  79. __u32 dropcount;
  80. };
  81. __u16 vlan_tci;
  82. sk_buff_data_t transport_header;
  83. sk_buff_data_t network_header;
  84. sk_buff_data_t mac_header;
  85. /* These elements must be at the end, see alloc_skb() for details. */
  86. sk_buff_data_t tail;
  87. sk_buff_data_t end;
  88. unsigned char *head,
  89. *data;
  90. unsigned int truesize;
  91. atomic_t users;
  92. };

可以看到新版本內核中發生了很多變化,其中數據包的首部在早期版本是以union的形式定義的,例如mac_header的定義方式如下:

  1. union{
  2. struct ethhdr *ethernet;
  3. unsigned char *raw;
  4. }mac;

這裡是以指針的形式給出的

  1. #ifdef NET_SKBUFF_DATA_USES_OFFSET
  2. typedef unsigned int sk_buff_data_t;
  3. #else
  4. typedef unsigned char *sk_buff_data_t;
  5. #endif
Copyright © Linux教程網 All Rights Reserved