svn commit: r325813 - head/sys/dev/vnic

Bjoern A. Zeeb bz at FreeBSD.org
Tue Nov 14 16:47:07 UTC 2017


Author: bz
Date: Tue Nov 14 16:47:05 2017
New Revision: 325813
URL: https://svnweb.freebsd.org/changeset/base/325813

Log:
  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
  In collaboration with:	emaste
  MFC after:		3 days

Modified:
  head/sys/dev/vnic/nicvf_queues.c

Modified: head/sys/dev/vnic/nicvf_queues.c
==============================================================================
--- head/sys/dev/vnic/nicvf_queues.c	Tue Nov 14 16:32:40 2017	(r325812)
+++ head/sys/dev/vnic/nicvf_queues.c	Tue Nov 14 16:47:05 2017	(r325813)
@@ -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);
 }


More information about the svn-src-all mailing list