Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154500
  • 博文数量: 41
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-14 10:16
文章分类
文章存档

2011年(1)

2010年(5)

2009年(35)

我的朋友

分类: LINUX

2009-08-20 12:47:46

tcp.c文件的tcp_err函数

978计划工作组 2009-8-20

1函数源码

/*

 * This routine is called by the ICMP module when it gets some

 * sort of error condition.  If err < 0 then the socket should

 * be closed and the error returned to the user.  If err > 0

 * it's just the icmp type << 8 | icmp code.  After adjustment

 * header points to the first 8 bytes of the tcp header.  We need

 * to find the appropriate port.

 */

 

void tcp_err(int err, unsigned char *header, unsigned long daddr,

       unsigned long saddr, struct inet_protocol *protocol)

{

       struct tcphdr *th;

       struct sock *sk;

       struct iphdr *iph=(struct iphdr *)header;

 

       header+=4*iph->ihl;

  

 

       th =(struct tcphdr *)header;

       sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);

 

       if (sk == NULL)

              return;

 

       if(err<0)

       {

             sk->err = -err;

             sk->error_report(sk);

             return;

       }

 

       if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8))

       {

              /*

               * FIXME:

               * For now we will just trigger a linear backoff.

               * The slow start code should cause a real backoff here.

               */

              if (sk->cong_window > 4)

                     sk->cong_window--;

              return;

       }

 

/*    sk->err = icmp_err_convert[err & 0xff].errno;  -- moved as TCP should hide non fatals internally (and does) */

 

       /*

        * If we've already connected we will keep trying

        * until we time out, or the user gives up.

        */

 

       if (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT)

       {

              if (sk->state == TCP_SYN_SENT)

              {

                     tcp_statistics.TcpAttemptFails++;

                     tcp_set_state(sk,TCP_CLOSE);

                     sk->error_report(sk);            /* Wake people up to see the error (see connect in sock.c) */

              }

              sk->err = icmp_err_convert[err & 0xff].errno;          

       }

       return;

}

}2函数用途

在系统接收到一个表示某种错误的数据包后,被ICMP 模块(icmp_rcv)调用,用于对使用TCP 协议的某个套接字进行处理。

3调用关系

4语句注释

4.1  sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);

tcp_prottcp协议处理函数集

th->source源端口号。

daddr目的地址。

th->dest目的端口号。

saddr源地址。

get_sock此函数定义在af_inet.c 中,用于根据TCP套接字四元素查询本地对应的sock结构。

4.2 if(err<0)

       {

            sk->err = -err;

            sk->error_report(sk);

            return;

       }

err<0如果错误号小于0,则表示这是一个较为严重的错误

sk->err=-err将错误存储到sock结构的err域中

sk->error_report此函数指针指向def_callback1函数,唤醒相关的线程。

4.3 if ((err & 0xff00) == (ICMP_SOURCE_QUENCH << 8))

       {

              if (sk->cong_window > 4)

                     sk->cong_window--;

       }

ICMP_SOURCE_QUENCH:是常数4,源端节制

sk->cong_window:节制窗口大小

err&oxff00:取高8位,即取得错误类型;高8位是错误类型,低8位是某类错误的具体错误

4.4  if (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT)

icmp_err_convert:是icmp_err结构类型的数组,此结构有两个域,error是错误类型,fatal标示该错误是否可恢复。

fatal:值为1表示不可恢复需要关闭并释放套接字,为0表示可恢复通信可继续进行

TCP_SYN_SEND同步信号已发送状态,该状态指客户端发送SYN数据包后(第一次握手)所处的状态。在接收到远端服务器端应答后(第二次握手),即从该状态进入TCP_ESTABLISHED状态

4.5  if (sk->state == TCP_SYN_SENT)

       {

              tcp_statistics.TcpAttemptFails++;

              tcp_set_state(sk,TCP_CLOSE);

              sk->error_report(sk);

       }

sk->state == TCP_SYN_SENT错误发生在连接过程中。

tcp_set_state:设置TCP的当前状态,TCP_CLOSE表示结束了此次连接

tcp_statistics.TcpAttemptFails连接失败次数统计。

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