1. 需求描述
有一个客户的统计需求是这样的:
1. The total number of successful TCP-connections through WAN port
2. Total the number of failed attempts TCP-connections WAN port
2. 需求分析
对以上需求,理解如下:
* 从LAN侧来,访问AP本身的包 ---------不需要统计
* 从LAN侧来,通过WAN口发送出去的包 ---------需要统计
* 由AP本身产生,通过WAN口发送出去的包 ---------需要统计
* 从WAN口进来,访问AP本身的包 ---------需要统计
以上说的不需要统计,是指需求里不需要这一项的结果。
以下描述将基于这样两个前提:
* LAN侧来的包的源地址,必须是跟我们的AP的br0是同一个网段的
* 本次统计只统计路由WAN连接的,而不统计桥WAN连接的
3. 需求实现
3.1 成功的统计
所谓成功就是看到REPLY包了的TCP连接,事实上,由于er3_tcp_success调用位置比较特殊,所以在调用er3_tcp_success时已经相当于IP_CT_ESTABLISHED状态了。
下面是代码(存在伪代码):
-
int er3_tcp_success_count = 0;
-
void er3_tcp_success(struct nf_conn *ct)
-
{
-
struct nf_conntrack_tuple *t = &(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-
u32 lan_ip = get_lan_ip();
-
-
-
// 1. <---- 不是TCP的不统计
-
if (t->dst.protonum != TCP)
-
{
-
return ;
-
}
-
-
-
// 2. <---- 从LAN侧访问AP本身的,不统计
-
if (t->dst.u3.ip == lan_ip)
-
{
-
return;
-
}
-
-
-
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
-
{
-
er3_tcp_success_count++;
-
}
-
-
-
return ;
-
}
-
-
-
resolve_normal_ct(...)
-
{
-
...
-
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
-
*ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
-
/* Please set reply bit if this packet OK */
-
*set_reply = 1;
-
} else {
-
/* Once we've had two way comms, always ESTABLISHED. */
-
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-
pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
-
*ctinfo = IP_CT_ESTABLISHED;
-
er3_tcp_success(ct);// 3. <---- 在这里调用er3_tcp_success进行统计
-
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
-
pr_debug("nf_conntrack_in: related packet for %p\n",
-
ct);
-
*ctinfo = IP_CT_RELATED;
-
} else {
-
pr_debug("nf_conntrack_in: new packet for %p\n", ct);
-
*ctinfo = IP_CT_NEW;
-
}
-
*set_reply = 0;
-
}
-
...
-
}
3.2 失败的包的统计
在这里,我们认为失败的TCP连接是这样的:到了超时了还没看到REPLY包。
下面是代码(存在伪代码):
-
int er3_tcp_fail_count = 0;
-
void er3_tcp_fail(struct nf_conn *ct)
-
{
-
struct nf_conntrack_tuple *t = &(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-
u32 lan_ip = get_lan_ip();
-
-
-
// 1. <---- 不是TCP的不统计
-
if (t->dst.protonum != TCP)
-
{
-
return ;
-
}
-
-
-
// 2. <---- 从LAN侧访问AP本身的,不统计
-
if (t->dst.u3.ip == lan_ip)
-
{
-
return;
-
}
-
-
-
//超时了还没看见回包的,肯定是失败的
-
if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
-
{
-
er3_tcp_fail_count++;
-
}
-
-
-
return ;
-
}
-
-
-
death_by_timeout(...)
-
{
-
...
-
er3_tcp_fail(ct); // 3. <---- 这里统计失败的。
-
spin_lock_bh(&nf_conntrack_lock);
-
/* Inside lock so preempt is disabled on module removal path.
-
* Otherwise we can get spurious warnings. */
-
NF_CT_STAT_INC(net, delete_list);
-
clean_from_lists(ct);
-
spin_unlock_bh(&nf_conntrack_lock);
-
nf_ct_put(ct);
-
}
这里还需要考虑用户使用flush_conntrack命令清除连接跟踪表的情况,因为在这种情况下,它即不是超时,也不是连接成功的情况。但是这种情况发生的概率还是比较小的,而且我们的统计应该允许有一定范围的误差吧。
阅读(2149) | 评论(0) | 转发(0) |