Fw: KASSERT when connect to the peer(system is running out of memory) .

fengdreamer fengdreamer at 126.com
Wed Dec 23 14:17:06 UTC 2009



2009-12-23



fengdreamer



发件人: fengdreamer
发送时间: 2009-12-22 22:05:20
收件人: freebsd-net
抄送: 
主题: KASSERT when connect to the peer(system is running out of memory) .

Hello ALL:

I am using the FreeBSD 7.1. My system is running out of memory, in this sidution when i create the socket and connect, the the KASSERT come out. Here is my description, please read the brief first and get the problem and then contnue with the detail description.

How is this problem happen:
Brief description:
1. First, Connect side send SYN to the listerner
2. Second, Connect side will retransmit the SYN packet, but when it alloc mbuf fail in the tcp_output. the tcp_sndnxt will not increase.
3. SYN ACK arrives, tcp_snduna increase, and will lager then tcp_sndnxt by 1. sender side will response the ACK, invoke tcp_output: len is 1, but cc is zero. KASSERT happen.

Detail description:
1.First, Connect side send SYN to the listerner, tcp->snd_nxt will just larger than the tcp->snd_una by 1.
2. Second, Connect side will retransmit the SYN packet. The retransmit is triger by the retransmit timer, it will then roll back the tcp->snd_nxt equal to tcp->snd_una.  and begin to call the tcp_output. If the tcp_output working fun, the tcp->snd_nxt will then advanced by 1 before it calls the ip_output. But if the mbuf alloc fail, the tcp->snd_nxt will stay equal to tcp->snd_una. (on my system, memery is running out, so mbuf alloc may fail. ) please refer the below code in the tcp_output:

MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
error = ENOBUFS;
goto out; // goto out, so the tcp->snd_nxt will not increased.
} 


3. as above describtion, the tcp->snd_nxt is equal to tcp->snd_una. then the SYN ACK packet arrives, and the connection is established, and the tcp->snd_una will increase by 1. Also the connect side will then send the last ACK, it invode the tcp_output, tcp output len is compute by the below expression:

off = tp->snd_nxt - tp->snd_una; 
len = ((long)ulmin(so->so_snd.sb_cc, sendwin) - off); 

ofcourse you have seen. the off is -1, the so_snd.sb_cc is 0, so the len is 1. so below KASSERT will came:

KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__)); /* (sbsndptr ) */

Thanks 
Regard


More information about the freebsd-net mailing list