全部博文(41)
分类: LINUX
2009-08-20 12:47:46
tcp.c文件的tcp_err函数
978计划工作组
/*
* 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;
}
在系统接收到一个表示某种错误的数据包后,被ICMP 模块(icmp_rcv)调用,用于对使用TCP 协议的某个套接字进行处理。。
tcp_prot:tcp协议处理函数集。
th->source:源端口号。
daddr:目的地址。
th->dest:目的端口号。
saddr:源地址。
get_sock:此函数定义在af_inet.c 中,用于根据TCP套接字四元素查询本地对应的sock结构。
err<0:如果错误号小于0,则表示这是一个较为严重的错误。
sk->err=-err:将错误存储到sock结构的err域中。
sk->error_report:此函数指针指向def_callback1函数,唤醒相关的线程。
ICMP_SOURCE_QUENCH:是常数4,源端节制。
sk->cong_window:节制窗口大小。
err&oxff00:取高8位,即取得错误类型;高8位是错误类型,低8位是某类错误的具体错误。
icmp_err_convert:是icmp_err结构类型的数组,此结构有两个域,error是错误类型,fatal标示该错误是否可恢复。
fatal:值为1表示不可恢复需要关闭并释放套接字,为0表示可恢复通信可继续进行。
TCP_SYN_SEND:同步信号已发送状态,该状态指客户端发送SYN数据包后(第一次握手)所处的状态。在接收到远端服务器端应答后(第二次握手),即从该状态进入TCP_ESTABLISHED状态。
sk->state == TCP_SYN_SENT:错误发生在连接过程中。
tcp_set_state:设置TCP的当前状态,TCP_CLOSE表示结束了此次连接。
tcp_statistics.TcpAttemptFails:连接失败次数统计。