https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264428
Bug ID: 264428 Summary: [tcp] Crash in sbsndptr Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: b...@freebsd.org Reporter: ram.gupta...@gmail.com Following is the analysis of the crash seen in sbsndptr in the stack. #0 0x0000ffff8ead225c in raise () from /usr/lib/libc.so.6 #1 0x0000ffff8ead3310 in abort () from /usr/lib/libc.so.6 #2 0x000000000097b238 in panic (fmt=fmt@entry=0xb7b9e0 "%s: sockbuf %p and mbuf %p clashing") at uinet_kern_shutdown.c:48 #3 0x0000000000915df4 in sbsndptr (sb=sb@entry=0x40003fff5188, off=<optimized out>, off@entry=462, len=len@entry=462, moff=moff@entry=0xffff79eb64c8) at /root/open_source/uinet/sys/kern/uipc_sockbuf.c:1025 #4 0x0000000000963d24 in tcp_output (tp=tp@entry=0x40003ffed000) at /root/open_source/uinet/sys/netinet/tcp_output.c:873 #5 0x0000000000970994 in tcp_output_send (tp=0x40003ffed000) at /root/open_source/uinet/sys/netinet/tcp_offload.h:282 #6 tcp_usr_send (so=0x40003fff5000, flags=0, m=<optimized out>, nam=0x0, control=<optimized out>, td=0xffff79ebb280) at /root/open_source/uinet/sys/netinet/tcp_usrreq.c:887 #7 0x00000000009185dc in sosend_generic (so=0x40003fff5000, addr=0xffff00000001, uio=0xffff79eb65f8, top=0x40003fd72000, control=0x1ce, flags=0, td=0xffff79eb65b0) at /root/open_source/uinet/sys/kern/uipc_socket.c:1528 #8 0x00000000009187a0 in sosend (so=<optimized out>, addr=<optimized out>, uio=uio@entry=0xffff79eb6608, top=top@entry=0x0, control=control@entry=0x0, flags=flags@entry=0, td=<optimized out>) at /root/open_source/uinet/sys/kern/uipc_socket.c:1574 The issue happens when trailing space becomes less than segment size. . This is where the problem starts as below 1) Sbcompress instead of incrementing mbuf len, sets the input mbuf to the sb->mb_tail next pointer. 2) It also calls sballoc where a new mbuf is stored in the socket buf. This mbuf is stored in sb->sb_mb pointer of send sockbuf. 3) At this point, the len is 462B, offset is 462B and sb_cc is 924B (one seg wating for ack and other to be sent) and sb_sndptroff is 462 4) When sbsndptr is called, it gets the new mbuf stored in step 2 which does not have m->next pointer at this point of time. 5) Offset calculated is (off - sb_sndptroff + len – 1) but since m->next pointer is null, panic is caused. Since the mbuf flag is not set to M_HOLE, Trailing space remains constant rather than increasing for accommodating new mbuf. static void sbdrop_internal(struct sockbuf *sb, int len) { … if (m->m_len > len) { m->m_len -= len; -> Increase TS if (!(m->m_flags & M_HOLE)) { m->m_data += len; -> Equalizes the TS } Where TS is (m)->m_ext.ext_buf + (m)->m_ext.ext_size - ((m)->m_data + (m)->m_len) So in nutshell, this condition hits in the following case where segment is being trying to be sent 1) TS shrinks to lower than m->m_len. (This condition is rare to happen if all acks for a particular mbuf are received at any point of time. If rcv’ed, mbuf is freed and sockbuf mbuf pointer is null. This resets the TS from 2048) 2) Unacknowledged data is one ACK away (off will be 462) 3) Length to be sent (462B) So the question is, on high pps environment, should m_flags be set to M_HOLE so TS can adjust dynamically. Thanks, Raman -- You are receiving this mail because: You are the assignee for the bug.