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
This commit is contained in:
parent
ed1838faed
commit
bdf4418a87
@ -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 qentry,
|
||||
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 qentry,
|
||||
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,72 +1806,71 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry,
|
||||
ip = (struct ip *)(mbuf->m_data + ehdrlen);
|
||||
iphlen = ip->ip_hl << 2;
|
||||
poff = ehdrlen + iphlen;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hdr->l3_offset = ehdrlen;
|
||||
hdr->l4_offset = ehdrlen + iphlen;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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++;
|
||||
}
|
||||
proto = ip->ip_p;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
hdr->csum_l3 = 0;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hdr->l3_offset = ehdrlen;
|
||||
hdr->l4_offset = poff;
|
||||
}
|
||||
|
||||
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 = 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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user