Date: Tue, 21 Nov 2017 15:34:26 +0000 (UTC) From: Ed Maste <emaste@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r326062 - stable/11/sys/dev/vnic Message-ID: <201711211534.vALFYQq8032839@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: emaste Date: Tue Nov 21 15:34:25 2017 New Revision: 326062 URL: https://svnweb.freebsd.org/changeset/base/326062 Log: MFC r325813 (bz): Unbreak IPv6. No longer return ENXIO when trying to send an IPv6 packet in nicvf_sq_add_hdr_subdesc(). Restructure the code so that the upper layer protocol parts are agnostic of the L3 protocol (and no longer specific to IPv4). With this basic IPv6 packets go through. We are still seeing weird behaviour which needs further diagnosis. PR: 223669 Modified: stable/11/sys/dev/vnic/nicvf_queues.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/vnic/nicvf_queues.c ============================================================================== --- stable/11/sys/dev/vnic/nicvf_queues.c Tue Nov 21 15:03:38 2017 (r326061) +++ stable/11/sys/dev/vnic/nicvf_queues.c Tue Nov 21 15:34:25 2017 (r326062) @@ -78,6 +78,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/tcp_lro.h> #include <netinet/udp.h> +#include <netinet6/ip6_var.h> + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -1752,7 +1754,7 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qen struct tcphdr *th; #endif uint16_t etype; - int ehdrlen, iphlen, poff; + int ehdrlen, iphlen, poff, proto; nic = sq->nic; @@ -1776,13 +1778,21 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qen etype = ntohs(eh->evl_encap_proto); } + poff = proto = -1; switch (etype) { #ifdef INET6 case ETHERTYPE_IPV6: - /* ARM64TODO: Add support for IPv6 */ - hdr->csum_l3 = 0; - sq->snd_buff[qentry].mbuf = NULL; - return (ENXIO); + if (mbuf->m_len < ehdrlen + sizeof(struct ip6_hdr)) { + mbuf = m_pullup(mbuf, ehdrlen +sizeof(struct ip6_hdr)); + sq->snd_buff[qentry].mbuf = NULL; + if (mbuf == NULL) + return (ENOBUFS); + } + poff = ip6_lasthdr(mbuf, ehdrlen, IPPROTO_IPV6, &proto); + if (poff < 0) + return (ENOBUFS); + poff += ehdrlen; + break; #endif #ifdef INET case ETHERTYPE_IP: @@ -1796,71 +1806,70 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qen ip = (struct ip *)(mbuf->m_data + ehdrlen); iphlen = ip->ip_hl << 2; poff = ehdrlen + iphlen; + proto = ip->ip_p; + break; +#endif + default: + hdr->csum_l3 = 0; + } - if (mbuf->m_pkthdr.csum_flags != 0) { - hdr->csum_l3 = 1; /* Enable IP csum calculation */ - switch (ip->ip_p) { - case IPPROTO_TCP: - if ((mbuf->m_pkthdr.csum_flags & CSUM_TCP) == 0) - break; - - if (mbuf->m_len < (poff + sizeof(struct tcphdr))) { - mbuf = m_pullup(mbuf, poff + sizeof(struct tcphdr)); - sq->snd_buff[qentry].mbuf = mbuf; - if (mbuf == NULL) - return (ENOBUFS); - } - hdr->csum_l4 = SEND_L4_CSUM_TCP; +#if defined(INET6) || defined(INET) + if (poff > 0 && mbuf->m_pkthdr.csum_flags != 0) { + hdr->csum_l3 = 1; /* Enable IP csum calculation */ + switch (proto) { + case IPPROTO_TCP: + if ((mbuf->m_pkthdr.csum_flags & CSUM_TCP) == 0) break; - case IPPROTO_UDP: - if ((mbuf->m_pkthdr.csum_flags & CSUM_UDP) == 0) - break; - if (mbuf->m_len < (poff + sizeof(struct udphdr))) { - mbuf = m_pullup(mbuf, poff + sizeof(struct udphdr)); - sq->snd_buff[qentry].mbuf = mbuf; - if (mbuf == NULL) - return (ENOBUFS); - } - hdr->csum_l4 = SEND_L4_CSUM_UDP; + if (mbuf->m_len < (poff + sizeof(struct tcphdr))) { + mbuf = m_pullup(mbuf, poff + sizeof(struct tcphdr)); + sq->snd_buff[qentry].mbuf = mbuf; + if (mbuf == NULL) + return (ENOBUFS); + } + hdr->csum_l4 = SEND_L4_CSUM_TCP; + break; + case IPPROTO_UDP: + if ((mbuf->m_pkthdr.csum_flags & CSUM_UDP) == 0) break; - case IPPROTO_SCTP: - if ((mbuf->m_pkthdr.csum_flags & CSUM_SCTP) == 0) - break; - if (mbuf->m_len < (poff + sizeof(struct sctphdr))) { - mbuf = m_pullup(mbuf, poff + sizeof(struct sctphdr)); - sq->snd_buff[qentry].mbuf = mbuf; - if (mbuf == NULL) - return (ENOBUFS); - } - hdr->csum_l4 = SEND_L4_CSUM_SCTP; + if (mbuf->m_len < (poff + sizeof(struct udphdr))) { + mbuf = m_pullup(mbuf, poff + sizeof(struct udphdr)); + sq->snd_buff[qentry].mbuf = mbuf; + if (mbuf == NULL) + return (ENOBUFS); + } + hdr->csum_l4 = SEND_L4_CSUM_UDP; + break; + case IPPROTO_SCTP: + if ((mbuf->m_pkthdr.csum_flags & CSUM_SCTP) == 0) break; - default: - break; + + if (mbuf->m_len < (poff + sizeof(struct sctphdr))) { + mbuf = m_pullup(mbuf, poff + sizeof(struct sctphdr)); + sq->snd_buff[qentry].mbuf = mbuf; + if (mbuf == NULL) + return (ENOBUFS); } - hdr->l3_offset = ehdrlen; - hdr->l4_offset = ehdrlen + iphlen; + hdr->csum_l4 = SEND_L4_CSUM_SCTP; + break; + default: + break; } + hdr->l3_offset = ehdrlen; + hdr->l4_offset = poff; + } - if ((mbuf->m_pkthdr.tso_segsz != 0) && nic->hw_tso) { - /* - * Extract ip again as m_data could have been modified. - */ - ip = (struct ip *)(mbuf->m_data + ehdrlen); - th = (struct tcphdr *)((caddr_t)ip + iphlen); + if ((mbuf->m_pkthdr.tso_segsz != 0) && nic->hw_tso) { + th = (struct tcphdr *)((caddr_t)(mbuf->m_data + poff)); - hdr->tso = 1; - hdr->tso_start = ehdrlen + iphlen + (th->th_off * 4); - hdr->tso_max_paysize = mbuf->m_pkthdr.tso_segsz; - hdr->inner_l3_offset = ehdrlen - 2; - nic->drv_stats.tx_tso++; - } - break; -#endif - default: - hdr->csum_l3 = 0; + hdr->tso = 1; + hdr->tso_start = poff + (th->th_off * 4); + hdr->tso_max_paysize = mbuf->m_pkthdr.tso_segsz; + hdr->inner_l3_offset = ehdrlen - 2; + nic->drv_stats.tx_tso++; } +#endif return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201711211534.vALFYQq8032839>