2024年3月28日发(作者:)

一.连接记录的存储

相关函数:

static inline struct nf_conn *nf_ct_tuplehash_to_ctrack(const struct

nf_conntrack_tuple_hash *hash)

static inline struct nf_conn *nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info

*ctinfo)

nf_conntrack中tuple存储如上图所示。在struct nf_conntrack_tuple_hash中,成员hnode链接入

ct->hash[]->first中的。实际的记录在保存在struct nf_conntrack_tuple中。

1.记录的访问:

hlist_nulls_for_each_entry_rcu

103 #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member)

104 for (pos = rcu_dereference((head)->first);

105 (!is_a_nulls(pos)) &&

106 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; });

107 pos = rcu_dereference(pos->next))

108

参见 /net/netfilter/nf_conntrack_core.c __nf_conntrack_find函数;

struct nf_conntrack_tuple_hash *h;

struct hlist_nulls_node *n;

hlist_nulls_for_each_entry_rcu(h, n, &net->[hash], hnnode)

2.记录的添加

84 static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,

85 struct hlist_nulls_head *h)

86 {

87 struct hlist_nulls_node *first = h->first;

88

89 n->next = first;

90 n->pprev = &h->first;

91 rcu_assign_pointer(h->first, n);

92 if (!is_a_nulls(first))

93 first->pprev = &n->next;

94 }

参见/net/netfilter/nf_conntrack_core.c:

313 static void __nf_conntrack_hash_insert(struct nf_conn *ct,

314 unsigned int hash,

315 unsigned int repl_hash)

316 {

317 struct net *net = nf_ct_net(ct);

318

319 hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,

320 &net->[hash]);

321 hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode,

322 &net->[repl_hash]);

323 }

3.记录的删除

59 static inline void hlist_nulls_del_rcu(struct hlist_nulls_node *n)

60 {

61 __hlist_nulls_del(n);

62 n->pprev = LIST_POISON2;

63 }

59 static inline void __hlist_nulls_del(struct hlist_nulls_node *n)

60 {

61 struct hlist_nulls_node *next = n->next;