kern/152853: [em] tftpd (and likely other udp traffic) fails
over em(4) unless rxcsum/txcsum disabled
Petr Lampa
lampa at fit.vutbr.cz
Tue Jan 18 15:20:12 UTC 2011
The following reply was made to PR kern/152853; it has been noted by GNATS.
From: Petr Lampa <lampa at fit.vutbr.cz>
To: bug-followup at FreeBSD.org, mandrews at bit0.com
Cc: jfv at 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 at 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--
More information about the freebsd-net
mailing list