From owner-freebsd-net@FreeBSD.ORG Tue Jan 18 15:20:12 2011 Return-Path: Delivered-To: freebsd-net@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B1A161065670 for ; Tue, 18 Jan 2011 15:20:12 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 854F08FC19 for ; Tue, 18 Jan 2011 15:20:12 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id p0IFKCUF001963 for ; Tue, 18 Jan 2011 15:20:12 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id p0IFKC6P001961; Tue, 18 Jan 2011 15:20:12 GMT (envelope-from gnats) Date: Tue, 18 Jan 2011 15:20:12 GMT Message-Id: <201101181520.p0IFKC6P001961@freefall.freebsd.org> To: freebsd-net@FreeBSD.org From: Petr Lampa Cc: Subject: Re: kern/152853: [em] tftpd (and likely other udp traffic) fails over em(4) unless rxcsum/txcsum disabled X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Petr Lampa List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Jan 2011 15:20:12 -0000 The following reply was made to PR kern/152853; it has been noted by GNATS. From: Petr Lampa To: bug-followup@FreeBSD.org, mandrews@bit0.com Cc: jfv@FreeBSD.org Subject: Re: kern/152853: [em] tftpd (and likely other udp traffic) fails over em(4) unless rxcsum/txcsum disabled Date: Tue, 18 Jan 2011 16:15:12 +0100 --y0ulUmNC+osPPQO6 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Some folowup for kern/152853 with a patch. It seems that the current version of if_em.c (both CURRENT and STABLE8) with txcsum/rxcsum cannot send any UDP packet shorter then TCP header size. The reason is suspicious m_pullup(m_head, poff + sizeof(struct tcphdr)) in common packet em_xmit handling. I've moved this m_pullupi() call to required branches further down and this fixed the issue (UDP ack from tftpd daemon now ok). The code however needs some audit, repeated m_pullups are strange. Sincerely, Petr Lampa *** if_em.c.old 2011-01-18 15:52:21.000000000 +0100 --- if_em.c 2011-01-18 15:58:11.000000000 +0100 *************** *** 1820,1831 **** } ip = (struct ip *)(mtod(m_head, char *) + ip_off); poff = ip_off + (ip->ip_hl << 2); - m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); - if (m_head == NULL) { - *m_headp = NULL; - return (ENOBUFS); - } if (do_tso) { tp = (struct tcphdr *)(mtod(m_head, char *) + poff); /* * TSO workaround: --- 1820,1831 ---- } ip = (struct ip *)(mtod(m_head, char *) + ip_off); poff = ip_off + (ip->ip_hl << 2); if (do_tso) { + m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } tp = (struct tcphdr *)(mtod(m_head, char *) + poff); /* * TSO workaround: *************** *** 1849,1854 **** --- 1849,1859 ---- tp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); } else if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { + m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } tp = (struct tcphdr *)(mtod(m_head, char *) + poff); m_head = m_pullup(m_head, poff + (tp->th_off << 2)); if (m_head == NULL) { -- Computer Centre E-mail: lampa@fit.vutbr.cz Faculty of Information Technology Web: http://www.fit.vutbr.cz/ Brno University of Technology Fax: +420 54114-1270 Bozetechova 2, 612 66 Brno, Czech Republic Phone: +420 54114-1225 --y0ulUmNC+osPPQO6 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="if_em.patch" *** if_em.c.old 2011-01-18 15:52:21.000000000 +0100 --- if_em.c 2011-01-18 15:58:11.000000000 +0100 *************** *** 1820,1831 **** } ip = (struct ip *)(mtod(m_head, char *) + ip_off); poff = ip_off + (ip->ip_hl << 2); - m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); - if (m_head == NULL) { - *m_headp = NULL; - return (ENOBUFS); - } if (do_tso) { tp = (struct tcphdr *)(mtod(m_head, char *) + poff); /* * TSO workaround: --- 1820,1831 ---- } ip = (struct ip *)(mtod(m_head, char *) + ip_off); poff = ip_off + (ip->ip_hl << 2); if (do_tso) { + m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } tp = (struct tcphdr *)(mtod(m_head, char *) + poff); /* * TSO workaround: *************** *** 1849,1854 **** --- 1849,1859 ---- tp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); } else if (m_head->m_pkthdr.csum_flags & CSUM_TCP) { + m_head = m_pullup(m_head, poff + sizeof(struct tcphdr)); + if (m_head == NULL) { + *m_headp = NULL; + return (ENOBUFS); + } tp = (struct tcphdr *)(mtod(m_head, char *) + poff); m_head = m_pullup(m_head, poff + (tp->th_off << 2)); if (m_head == NULL) { --y0ulUmNC+osPPQO6--