Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/virtio/network/if_vtnet.c
Show First 20 Lines • Show All 2,383 Lines • ▼ Show 20 Lines | default: | ||||
sc->vtnet_stats.tx_csum_unknown_ethtype++; | sc->vtnet_stats.tx_csum_unknown_ethtype++; | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vtnet_txq_offload_tso(struct vtnet_txq *txq, struct mbuf *m, int flags, | vtnet_txq_offload_tso(struct vtnet_txq *txq, struct mbuf *m, int eth_type, | ||||
int offset, struct virtio_net_hdr *hdr) | int offset, struct virtio_net_hdr *hdr) | ||||
{ | { | ||||
static struct timeval lastecn; | static struct timeval lastecn; | ||||
static int curecn; | static int curecn; | ||||
struct vtnet_softc *sc; | struct vtnet_softc *sc; | ||||
struct tcphdr *tcp, tcphdr; | struct tcphdr *tcp, tcphdr; | ||||
sc = txq->vtntx_sc; | sc = txq->vtntx_sc; | ||||
if (__predict_false(m->m_len < offset + sizeof(struct tcphdr))) { | if (__predict_false(m->m_len < offset + sizeof(struct tcphdr))) { | ||||
m_copydata(m, offset, sizeof(struct tcphdr), (caddr_t) &tcphdr); | m_copydata(m, offset, sizeof(struct tcphdr), (caddr_t) &tcphdr); | ||||
tcp = &tcphdr; | tcp = &tcphdr; | ||||
} else | } else | ||||
tcp = (struct tcphdr *)(m->m_data + offset); | tcp = (struct tcphdr *)(m->m_data + offset); | ||||
hdr->hdr_len = vtnet_gtoh16(sc, offset + (tcp->th_off << 2)); | hdr->hdr_len = vtnet_gtoh16(sc, offset + (tcp->th_off << 2)); | ||||
hdr->gso_size = vtnet_gtoh16(sc, m->m_pkthdr.tso_segsz); | hdr->gso_size = vtnet_gtoh16(sc, m->m_pkthdr.tso_segsz); | ||||
hdr->gso_type = (flags & CSUM_IP_TSO) ? | hdr->gso_type = eth_type == ETHERTYPE_IP ? VIRTIO_NET_HDR_GSO_TCPV4 : | ||||
VIRTIO_NET_HDR_GSO_TCPV4 : VIRTIO_NET_HDR_GSO_TCPV6; | VIRTIO_NET_HDR_GSO_TCPV6; | ||||
if (__predict_false(tcp->th_flags & TH_CWR)) { | if (__predict_false(tcp->th_flags & TH_CWR)) { | ||||
/* | /* | ||||
* Drop if VIRTIO_NET_F_HOST_ECN was not negotiated. In | * Drop if VIRTIO_NET_F_HOST_ECN was not negotiated. In | ||||
* FreeBSD, ECN support is not on a per-interface basis, | * FreeBSD, ECN support is not on a per-interface basis, | ||||
* but globally via the net.inet.tcp.ecn.enable sysctl | * but globally via the net.inet.tcp.ecn.enable sysctl | ||||
* knob. The default is off. | * knob. The default is off. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (__predict_false(proto != IPPROTO_TCP)) { | ||||
sc->vtnet_stats.tx_tso_not_tcp++; | sc->vtnet_stats.tx_tso_not_tcp++; | ||||
goto drop; | goto drop; | ||||
} else if (__predict_false((hdr->flags & | } else if (__predict_false((hdr->flags & | ||||
VIRTIO_NET_HDR_F_NEEDS_CSUM) == 0)) { | VIRTIO_NET_HDR_F_NEEDS_CSUM) == 0)) { | ||||
sc->vtnet_stats.tx_tso_without_csum++; | sc->vtnet_stats.tx_tso_without_csum++; | ||||
goto drop; | goto drop; | ||||
} | } | ||||
error = vtnet_txq_offload_tso(txq, m, flags, csum_start, hdr); | error = vtnet_txq_offload_tso(txq, m, etype, csum_start, hdr); | ||||
if (error) | if (error) | ||||
goto drop; | goto drop; | ||||
} | } | ||||
return (m); | return (m); | ||||
drop: | drop: | ||||
m_freem(m); | m_freem(m); | ||||
▲ Show 20 Lines • Show All 1,941 Lines • Show Last 20 Lines |