主动关闭 time-wait 2msl 处理
先上传后面整理
/*
* 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.
*
* The locking strategy used here is very "optimistic". When
* someone else accesses the socket the ICMP is just dropped
* and for some paths there is no check at all.
* A more general error queue to queue errors for later handling
* is probably better.
*
*/
/*
* 目的不可达、源端被关闭、超时、参数错误这四种类型
* 的差错ICMP报文,都是由同一个函数icmp_unreach()来处理的,
* 对其中目的不可达、源端被关闭这两种类型ICMP报文
* 因要提取某些信息而需作一些特殊的处理,而另外
* 一些则不需要,根据差错报文中的信息直接调用
* 传输层的错误处理例程。参见<Linux内核源码剖析348页>
CMP差错报文的数据部分包括:原始数据报的IP首部再加上前8个字节的数据部分(2字节源端口+2字节目的端口+4字节序号)
*/
void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
{
struct iphdr *iph = (struct iphdr *)icmp_skb->data;
struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
struct inet_connection_sock *icsk;
struct tcp_sock *tp;
struct inet_sock *inet;
const int type = icmp_hdr(icmp_skb)->type;
const int code = icmp_hdr(icmp_skb)->code;
struct sock *sk;
struct sk_buff *skb;
__u32 seq;
__u32 remaining;
int err;
struct net *net = dev_net(icmp_skb->dev); /*
* 检测ICMP报文长度是否包含了原始IP首部和原始IP数据包中
* 前8字节数据,如果不完整则返回
*/
if (icmp_skb->len < (iph->ihl << 2) + 8) {
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
return;
} /*
* 通过从ICMP报文数据中获取的原始TCP首部中源端口号和IP首部
* 中源地址,得到发送该TCP报文的传输控制块。如果获取失败,
* 则说明ICMP报文有误或该套接字已关闭;如果获取传输控制块
* 的TCP状态为TIME_WAIT,则说明套接字即将关闭,这两种情况
* 都无需进一步处理
*/
sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest,
iph->saddr, th->source, inet_iif(icmp_skb));
if (!sk) {
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
return;
}
if (sk->sk_state == TCP_TIME_WAIT) {
inet_twsk_put(inet_twsk(sk));
return;
} bh_lock_sock(sk);
/* If too many ICMPs get dropped on busy
* servers this needs to be solved differently.
*//*
* 如果此时该传输控制块被用户进程锁定(如用户进程正在调用
* send等系统调用),则需累计相关SNMP的统计量
*/
if (sock_owned_by_user(sk))
NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); if (sk->sk_state == TCP_CLOSE)
goto out; if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
goto out;
} /*
* 如果传输控制块不再侦听状态,且序号不再已发送未确认的区间内,则
* ICMP报文异常,无需进一步处理
*/ icsk = inet_csk(sk);
tp = tcp_sk(sk);
seq = ntohl(th->seq);
if (sk->sk_state != TCP_LISTEN &&
!between(seq, tp->snd_una, tp->snd_nxt)) {
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
} switch (type) {
case ICMP_SOURCE_QUENCH:
/* Just silently ignore these. */
goto out;
case ICMP_PARAMETERPROB:
err = EPROTO;
break;
/*
* 处理目的不可达类型,首先检测代码的合法性,然后根据
* 代码具体处理:如果需要分片而设置了不可分片,则调用
* do_pmtu_discovery()探测路径MTU;其他编码,则获取
* 对应的错误码
*/
case ICMP_DEST_UNREACH:
if (code > NR_ICMP_UNREACH)
goto out; if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
if (!sock_owned_by_user(sk))
do_pmtu_discovery(sk, iph, info);
goto out;
} err = icmp_err_convert[code].errno;
/* check if icmp_skb allows revert of backoff
* (see draft-zimmermann-tcp-lcd) */
if (code != ICMP_NET_UNREACH && code != ICMP_HOST_UNREACH)
break;
if (seq != tp->snd_una || !icsk->icsk_retransmits ||
!icsk->icsk_backoff)
break; if (sock_owned_by_user(sk))
break; icsk->icsk_backoff--;
inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) <<
icsk->icsk_backoff;
tcp_bound_rto(sk); skb = tcp_write_queue_head(sk);
BUG_ON(!skb); remaining = icsk->icsk_rto - min(icsk->icsk_rto,
tcp_time_stamp - TCP_SKB_CB(skb)->when); if (remaining) {
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
remaining, TCP_RTO_MAX);
} else {
/* RTO revert clocked out retransmission.
* Will retransmit now */
tcp_retransmit_timer(sk);
} break;
case ICMP_TIME_EXCEEDED:
err = EHOSTUNREACH;
break;
default:
goto out;
} switch (sk->sk_state) {
struct request_sock *req, **prev;
case TCP_LISTEN:
/*
* 如果传输控制块被用户进程锁定,则不作进一步处理
*/
if (sock_owned_by_user(sk))
goto out; /*
* 由于处于监听状态,因此根据目的端口号、源地址和目的地址查找
* 正在连接的对端套接字,如果查找失败则不作进一步处理
*/
req = inet_csk_search_req(sk, &prev, th->dest,
iph->daddr, iph->saddr);
if (!req)
goto out; /* ICMPs are not backlogged, hence we cannot get
an established socket here.
*/
WARN_ON(req->sk); /*
* 如果发送出去TCP段的序号不等于对端套接字中的发送序号,
* 则说明序号有误,不作进一步处理
*/
if (seq != tcp_rsk(req)->snt_isn) {
NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
} /*
* Still in SYN_RECV, just remove it silently.
* There is no good way to pass the error to the newly
* created socket, and POSIX does not want network
* errors returned from accept().
*/
/*
* 删除并释放连接过程中的传输控制块
*/
inet_csk_reqsk_queue_drop(sk, req, prev);
goto out; case TCP_SYN_SENT:
case TCP_SYN_RECV: /* Cannot happen.
It can f.e. if SYNs crossed.
*//*
* 如果传输控制块没有被用户进程锁定,则将错误码设置到sk_err,
* 调用该套接字的错误报告借口函数,关闭套接字;否则将错误码
* 设置到sk_err_soft,在这种情况下用户进程可使用SO_ERROR套接
* 字选项获取错误码
*/
if (!sock_owned_by_user(sk)) {
sk->sk_err = err; sk->sk_error_report(sk); tcp_done(sk);
} else {
sk->sk_err_soft = err;
}
goto out;
} /* If we've already connected we will keep trying
* until we time out, or the user gives up.
*
* rfc1122 4.2.3.9 allows to consider as hard errors
* only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
* but it is obsoleted by pmtu discovery).
*
* Note, that in modern internet, where routing is unreliable
* and in each dark corner broken firewalls sit, sending random
* errors ordered by their masters even this two messages finally lose
* their original sense (even Linux sends invalid PORT_UNREACHs)
*
* Now we are in compliance with RFCs.
* --ANK (980905)
*/ /*
* 到这一步,则传输控制块一定不再LISTEN、SYN_SENT或SYN_RECV状态,
* 此时如果控制块没有被用户进程锁定,并且允许接收扩展的可靠错误
* 信息,则设置得到的错误码,然后通知错误;否则将错误码设置到sk_err_soft
*/
inet = inet_sk(sk);
if (!sock_owned_by_user(sk) && inet->recverr) {
sk->sk_err = err;
sk->sk_error_report(sk);
} else { /* Only an error on timeout */
sk->sk_err_soft = err;
} out:
bh_unlock_sock(sk);
sock_put(sk);
}
主动关闭 time-wait 2msl 处理的更多相关文章
- 关于TCP主动关闭连接中的wait_timeout
首先我们先来回顾一下tcp关闭连接的过程: 假设A和B连接状态为EST,A需要主动关闭: A发送FIN给B,并将状态更改为FIN_WAIT1, B接收到FIN将状态更改为CLOSE_WAIT,并回复A ...
- 主动关闭 tcp_timewait_state_process 处理
正常情况下主动关闭连接的一端在连接正常终止后,会进入TIME_WAIT状态,存在这个状态有以下两个原因(参考<Unix网络编程>): 1.保证TCP连接关闭的可靠性.如果最终发送 ...
- 主动关闭 tcp fin-wait-2 time-wait 定时器
后面整理相关信息 //后面整理相关信息 /* * This function implements the receiving procedure of RFC 793 for * all state ...
- Dialog中显示倒计时,到时自己主动关闭
这里直接用系统Dialog中加入了倒计时的显示,假设用自己定义Dialog会更美观: private TextView mOffTextView; private Handler mOffHandle ...
- [C++] 自己主动关闭右下角弹窗
近期腾讯.迅雷等各种client,都越发喜欢在屏幕的右下角弹框了. 有骨气的人当然能够把这些软件卸载了事,可是这些client在某些情况下却又还是实用的.怎么办呢? 作为码农,自己实现一个自己主动关闭 ...
- 封装WebSocket(建立链接、主动关闭)
一.前言 近期项目里需做一个在线聊天功能,就想要在对话的时候建立socket链接.又因为聊天只是其中一个部分,在它外面还有一些全局的消息通知需要接收,因此也需要建立socket链接.在该项目里不仅一处 ...
- 主动关闭 time wait结构体
/* * This is a TIME_WAIT sock. It works around the memory consumption * problems of sockets in such ...
- TCP三次握手及关闭时的2MSL分析
TCP/IP三次握手四次挥手,是非常重要的,这个链接与关闭过程也是非常easy的.但为什么是三次握手?以及为什么要等待2MSL的状态?大部分人或许听到这个问题就蒙了.这篇博客就综合<TCP/IP ...
- vue使用layer主动关闭弹窗
关闭当前框的弹出层 layer.close(layer.index); 刷新父层 parent.location.reload(); // 父页面刷新 关闭iframe 弹出的全屏层 var inde ...
随机推荐
- “3D引擎和图形学技术点思路讲解”线上直播培训班报名开始啦(完全免费)
大家好,我开了一个线上的直播课程培训班,完全免费,欢迎大家报名! 本课程重点教授"光线追踪"方面的实现思路. 我的相关经验 5年3D引擎开发经验 Wonder-WebGL 3D引擎 ...
- 多测师讲解html _无序列表006_高级讲师肖sir
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>无 ...
- 基于python实现顺序存储的栈
""" 栈 sstack.py 栈模型的顺序存储 重点代码 思路总结: 1.列表是顺序存储,但功能多,不符合栈的模型特征 2.利用列表,将其封装,提供接口方法 " ...
- 【C语言教程】双向链表学习总结和C语言代码实现!值得学习~
双向链表 定义 我们一开始学习的链表中各节点中都只包含一个指针(游标),且都统一指向直接后继节点,通常称这类链表为单向链表. 虽然使用单向链表能 100% 解决逻辑关系为 "一对一" ...
- 理解Go协程与并发(转)
理解Go协程与并发 协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: Copy package main import ( "fmt" " ...
- PyCharm搭配github错误处理
ssh -T git@github.com 验证时 报错Could not open a connection to your authentication agent. 删除前面生成的.ssh文件 ...
- JAVA中Object类方法详解
一.引言 Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类.大家天天都在使用toString().equals().hashCode().waite().notify() ...
- Linux系统及第三方应用官方文档
通过在线文档获取帮助 http://www.github.com https://www.kernel.org/doc/html/latest/ http://httpd.apache.org htt ...
- STL: set和map的区别、联系、使用
set是一种关联式容器,其特性如下: set以RBTree作为底层容器 所得元素的只有key(键)没有value(值) 不允许出现键重复 所有的元素都会被自动排序 不能通过迭代器来改变set的值,因为 ...
- 解决Java连接Oracle 12c存在的问题
感谢作者 原文链接:https://blog.csdn.net/peng_wei_kang/article/details/80403486 1.发现项目报以下错误: Caused by: jav ...