Chinaunix首页 | 论坛 | 博客
  • 博客访问: 175468
  • 博文数量: 33
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 501
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-26 11:00
文章分类

全部博文(33)

文章存档

2014年(11)

2013年(22)

我的朋友

分类: LINUX

2013-03-27 12:47:04

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状态了。

下面是代码(存在伪代码):

点击(此处)折叠或打开

  1. int er3_tcp_success_count = 0;
  2. void er3_tcp_success(struct nf_conn *ct)
  3. {
  4.     struct nf_conntrack_tuple *t = &(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
  5.     u32 lan_ip = get_lan_ip();


  6.     // 1. <---- 不是TCP的不统计
  7.     if (t->dst.protonum != TCP)
  8.     {
  9.         return ;
  10.     }


  11.     // 2. <---- 从LAN侧访问AP本身的,不统计
  12.     if (t->dst.u3.ip == lan_ip)
  13.     {
  14.         return;
  15.     }


  16.     if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
  17.     {
  18.         er3_tcp_success_count++;
  19.     }


  20.     return ;
  21. }


  22. resolve_normal_ct(...)
  23. {
  24.     ...
  25.     if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
  26.         *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
  27.         /* Please set reply bit if this packet OK */
  28.         *set_reply = 1;
  29.     } else {
  30.         /* Once we've had two way comms, always ESTABLISHED. */
  31.         if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
  32.             pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
  33.             *ctinfo = IP_CT_ESTABLISHED;
  34.             er3_tcp_success(ct);// 3. <---- 在这里调用er3_tcp_success进行统计
  35.         } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
  36.             pr_debug("nf_conntrack_in: related packet for %p\n",
  37.                  ct);
  38.             *ctinfo = IP_CT_RELATED;
  39.         } else {
  40.             pr_debug("nf_conntrack_in: new packet for %p\n", ct);
  41.             *ctinfo = IP_CT_NEW;
  42.         }
  43.         *set_reply = 0;
  44.     }
  45.     ...
  46. }




3.2 失败的包的统计

在这里,我们认为失败的TCP连接是这样的:到了超时了还没看到REPLY包。

下面是代码(存在伪代码):

点击(此处)折叠或打开

  1. int er3_tcp_fail_count = 0;
  2. void er3_tcp_fail(struct nf_conn *ct)
  3. {
  4.     struct nf_conntrack_tuple *t = &(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
  5.     u32 lan_ip = get_lan_ip();


  6.     // 1. <---- 不是TCP的不统计
  7.     if (t->dst.protonum != TCP)
  8.     {
  9.         return ;
  10.     }


  11.     // 2. <---- 从LAN侧访问AP本身的,不统计
  12.     if (t->dst.u3.ip == lan_ip)
  13.     {
  14.         return;
  15.     }


  16.     //超时了还没看见回包的,肯定是失败的
  17.     if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
  18.     {
  19.         er3_tcp_fail_count++;
  20.     }


  21.     return ;
  22. }


  23. death_by_timeout(...)
  24. {
  25.     ...
  26.     er3_tcp_fail(ct); // 3. <---- 这里统计失败的。
  27.     spin_lock_bh(&nf_conntrack_lock);
  28.     /* Inside lock so preempt is disabled on module removal path.
  29.      * Otherwise we can get spurious warnings. */
  30.     NF_CT_STAT_INC(net, delete_list);
  31.     clean_from_lists(ct);
  32.     spin_unlock_bh(&nf_conntrack_lock);
  33.     nf_ct_put(ct);
  34. }
这里还需要考虑用户使用flush_conntrack命令清除连接跟踪表的情况,因为在这种情况下,它即不是超时,也不是连接成功的情况。但是这种情况发生的概率还是比较小的,而且我们的统计应该允许有一定范围的误差吧。



阅读(2155) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~