I'm running into an interaction between a 3rd party 10GbE driver and the NREAD getsockopt() call.
My kext is reading data from the TCP/IP stack using the sock_receivembuf() KPI. The received mbuf chain eventually gets relayed to another kext via a kern_control socket (also read using sock_receivembuf). Since sock_receivembuf() requires that the caller specify the number of bytes to return in the mbuf chain, the client has to call the SO_NREAD getsockopt (which is unfortunate since kern_control sockets are PR_ATOMIC) to determine this value.
My problem occurs when the TCP/IP stack returns an mbuf chain in which one of the mbufs has a type of MT_HEADER. The SO_NREAD only counts MT_DATA mbufs in the total byte count causing SO_NREAD to return a short value of what is actually buffered. Since the kern_control socket is PR_ATOMIC, the first read will consume the entire record (but only return the short-count of data), and I've lost the remaining data.
My question: Is this a bug where the TCP/IP stack or the 10GbE driver shouldn't be returning MT_HEADER mbufs that are carrying data, or SO_NREAD being too selective about what it considers data?
From uipc_socket.c: sogetopt() case SO_NREAD: { int pkt_total; struct mbuf *m1;
pkt_total = 0; m1 = so->so_rcv.sb_mb; if (so->so_proto->pr_flags & PR_ATOMIC) { while (m1) { if (m1->m_type == MT_DATA) pkt_total += m1->m_len; m1 = m1->m_next; } optval = pkt_total; } else optval = so->so_rcv.sb_cc; goto integer; }
---- Thanks, Matt
|