Module Name: src Committed By: jdolecek Date: Mon Mar 16 20:49:22 UTC 2020
Modified Files: src/sys/arch/xen/xen: if_xennet_xenbus.c xennet_checksum.c xennetback_xenbus.c Log Message: drop the disabled M_EXT_ROMAP mbuf code, and convert xennet_checksum_fill() to use in_undefer_cksum() instead of custom code to compute the checksum for incoming packets make it possible to defer/skip the checksum computation by appropriate Rx flag similarily as we do for Tx; with To generate a diff of this commit: cvs rdiff -u -r1.88 -r1.89 src/sys/arch/xen/xen/if_xennet_xenbus.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/xen/xen/xennet_checksum.c cvs rdiff -u -r1.76 -r1.77 src/sys/arch/xen/xen/xennetback_xenbus.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/xen/xen/if_xennet_xenbus.c diff -u src/sys/arch/xen/xen/if_xennet_xenbus.c:1.88 src/sys/arch/xen/xen/if_xennet_xenbus.c:1.89 --- src/sys/arch/xen/xen/if_xennet_xenbus.c:1.88 Wed Jan 29 05:41:48 2020 +++ src/sys/arch/xen/xen/if_xennet_xenbus.c Mon Mar 16 20:49:22 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_xennet_xenbus.c,v 1.88 2020/01/29 05:41:48 thorpej Exp $ */ +/* $NetBSD: if_xennet_xenbus.c,v 1.89 2020/03/16 20:49:22 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -84,7 +84,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.88 2020/01/29 05:41:48 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.89 2020/03/16 20:49:22 jdolecek Exp $"); #include "opt_xen.h" #include "opt_nfs_boot.h" @@ -386,7 +386,9 @@ xennet_xenbus_attach(device_t parent, de ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_timer = 0; ifp->if_snd.ifq_maxlen = uimax(ifqmaxlen, NET_TX_RING_SIZE * 2); - ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; + ifp->if_capabilities = + IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx + | IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); @@ -1119,12 +1121,7 @@ again: m->m_flags |= M_EXT_RW; /* we own the buffer */ } if ((rx->flags & NETRXF_csum_blank) != 0) { - xennet_checksum_fill(&m); - if (m == NULL) { - if_statinc(ifp, if_ierrors); - xennet_rx_free_req(req); - continue; - } + xennet_checksum_fill(ifp, m); } /* free req may overwrite *rx, better doing it late */ xennet_rx_free_req(req); Index: src/sys/arch/xen/xen/xennet_checksum.c diff -u src/sys/arch/xen/xen/xennet_checksum.c:1.4 src/sys/arch/xen/xen/xennet_checksum.c:1.5 --- src/sys/arch/xen/xen/xennet_checksum.c:1.4 Sat Mar 14 11:52:12 2020 +++ src/sys/arch/xen/xen/xennet_checksum.c Mon Mar 16 20:49:22 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xennet_checksum.c,v 1.4 2020/03/14 11:52:12 jdolecek Exp $ */ +/* $NetBSD: xennet_checksum.c,v 1.5 2020/03/16 20:49:22 jdolecek Exp $ */ /*- * Copyright (c)2006 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xennet_checksum.c,v 1.4 2020/03/14 11:52:12 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xennet_checksum.c,v 1.5 2020/03/16 20:49:22 jdolecek Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -39,73 +39,51 @@ __KERNEL_RCSID(0, "$NetBSD: xennet_check #include <netinet/in.h> #include <netinet/in_systm.h> +#include <netinet/in_offload.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <xen/xennet_checksum.h> -static const void *m_extract(struct mbuf *, int, int, void *); -static void *m_extract_write(struct mbuf *, int, int, void *); - -static void *m_extract1(struct mbuf *, int, int, void *, int); -#define MBUF_EXTRACT_WRITE 1 +/* ratecheck(9) for checksum validation failures */ +static const struct timeval xn_cksum_errintvl = { 600, 0 }; /* 10 min, each */ static void * -m_extract1(struct mbuf *m, int off, int len, void *buf, int flags) -{ - void *result; - - KASSERT((m->m_flags & M_PKTHDR) != 0); - - if (m->m_pkthdr.len < off + len) { - result = NULL; - } else if (m->m_len >= off + len && - ((flags & MBUF_EXTRACT_WRITE) != 0 || !M_READONLY(m))) { - result = mtod(m, char *) + off; - } else { - m_copydata(m, off, len, buf); - result = buf; - } - - return result; -} - -static const void * -m_extract(struct mbuf *m, int off, int len, void *buf) +m_extract(struct mbuf *m, int off, int len) { + KASSERT(m->m_pkthdr.len >= off + len); + KASSERT(m->m_len >= off + len); - return m_extract1(m, off, len, buf, 0); -} - -static void * -m_extract_write(struct mbuf *m, int off, int len, void *buf) -{ - - return m_extract1(m, off, len, buf, MBUF_EXTRACT_WRITE); + if (m->m_pkthdr.len >= off + len) + return mtod(m, char *) + off; + else + return NULL; } /* - * xennet_checksum_fill: fill TCP/UDP checksum + * xennet_checksum_fill: fill TCP/UDP checksum, or arrange + * for hw offload to do it */ - int -xennet_checksum_fill(struct mbuf **mp) +xennet_checksum_fill(struct ifnet *ifp, struct mbuf *m) { - struct mbuf *m = *mp; - struct ether_header eh_store; const struct ether_header *eh; - struct ip iph_store; - const struct ip *iph; + struct ip *iph; int ehlen; int iphlen; int iplen; uint16_t etype; uint8_t nxt; int error = 0; + int sw_csum; + + KASSERT(!M_READONLY(m)); + KASSERT((m->m_flags & M_PKTHDR) != 0); - eh = m_extract(m, 0, sizeof(*eh), &eh_store); + eh = m_extract(m, 0, sizeof(*eh)); if (eh == NULL) { + /* Too short, packet will be dropped by upper layer */ return EINVAL; } etype = eh->ether_type; @@ -114,69 +92,58 @@ xennet_checksum_fill(struct mbuf **mp) } else if (etype == htobe16(ETHERTYPE_IP)) { ehlen = ETHER_HDR_LEN; } else { + static struct timeval lasttime; + if (ratecheck(&lasttime, &xn_cksum_errintvl)) + printf("%s: unknown etype %#x passed no checksum\n", + ifp->if_xname, ntohs(etype)); return EINVAL; } - iph = m_extract(m, ehlen, sizeof(*iph), &iph_store); + iph = m_extract(m, ehlen, sizeof(*iph)); if (iph == NULL) { + /* Too short, packet will be dropped by upper layer */ return EINVAL; } nxt = iph->ip_p; - iphlen = iph->ip_hl * 4; + iphlen = iph->ip_hl << 2; iplen = ntohs(iph->ip_len); if (ehlen + iplen > m->m_pkthdr.len) { + /* Too short, packet will be dropped by upper layer */ return EINVAL; } - if (nxt == IPPROTO_UDP) { - struct udphdr uh_store; - struct udphdr *uh; - int ulen; - - uh = m_extract_write(m, ehlen + iphlen, sizeof(*uh), &uh_store); - ulen = ntohs(uh->uh_ulen); - if (ehlen + iphlen + ulen > m->m_pkthdr.len) { - return EINVAL; - } - m->m_len -= ehlen; - m->m_data += ehlen; - uh->uh_sum = 0; - uh->uh_sum = in4_cksum(m, nxt, iphlen, iplen - iphlen); - m->m_len += ehlen; - m->m_data -= ehlen; - if (uh != &uh_store) { - m = m_copyback_cow(m, ehlen + iphlen, sizeof(*uh), uh, - M_DONTWAIT); - if (m == NULL) { - error = ENOMEM; - } - } - } else if (nxt == IPPROTO_TCP) { - struct tcphdr th_store; - struct tcphdr *th; - int thlen; - - th = m_extract_write(m, ehlen + iphlen, sizeof(*th), &th_store); - thlen = th->th_off * 4; - if (ehlen + iphlen + thlen > m->m_pkthdr.len) { - return EINVAL; - } - m->m_len -= ehlen; - m->m_data += ehlen; - th->th_sum = 0; - th->th_sum = in4_cksum(m, nxt, iphlen, iplen - iphlen); - m->m_len += ehlen; - m->m_data -= ehlen; - if (th != &th_store) { - m = m_copyback_cow(m, ehlen + iphlen, sizeof(*th), th, - M_DONTWAIT); - if (m == NULL) { - error = ENOMEM; - } - } - } else { + + switch (nxt) { + case IPPROTO_UDP: + m->m_pkthdr.csum_flags = M_CSUM_UDPv4; + m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); + m->m_pkthdr.csum_data |= iphlen << 16; + break; + case IPPROTO_TCP: + m->m_pkthdr.csum_flags = M_CSUM_TCPv4; + m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + m->m_pkthdr.csum_data |= iphlen << 16; + break; + default: + { + static struct timeval lasttime; + if (ratecheck(&lasttime, &xn_cksum_errintvl)) + printf("%s: unknown proto %d passed no checksum\n", + ifp->if_xname, nxt); error = EINVAL; + goto out; + } + } + + /* + * Only compute the checksum if impossible to defer. + */ + sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_rx; + + if (sw_csum & (M_CSUM_UDPv4|M_CSUM_TCPv4)) { + in_undefer_cksum(m, ehlen, + sw_csum & (M_CSUM_UDPv4|M_CSUM_TCPv4)); } - *mp = m; + out: return error; } Index: src/sys/arch/xen/xen/xennetback_xenbus.c diff -u src/sys/arch/xen/xen/xennetback_xenbus.c:1.76 src/sys/arch/xen/xen/xennetback_xenbus.c:1.77 --- src/sys/arch/xen/xen/xennetback_xenbus.c:1.76 Wed Jan 29 05:41:48 2020 +++ src/sys/arch/xen/xen/xennetback_xenbus.c Mon Mar 16 20:49:22 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xennetback_xenbus.c,v 1.76 2020/01/29 05:41:48 thorpej Exp $ */ +/* $NetBSD: xennetback_xenbus.c,v 1.77 2020/03/16 20:49:22 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.76 2020/01/29 05:41:48 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.77 2020/03/16 20:49:22 jdolecek Exp $"); #include "opt_xen.h" @@ -90,7 +90,7 @@ struct xni_pkt { /* pools for xni_pkt */ struct pool xni_pkt_pool; /* ratecheck(9) for pool allocation failures */ -struct timeval xni_pool_errintvl = { 30, 0 }; /* 30s, each */ +static const struct timeval xni_pool_errintvl = { 30, 0 }; /* 30s, each */ /* state of a xnetback instance */ typedef enum { @@ -301,7 +301,9 @@ xennetback_xenbus_create(struct xenbus_d ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_snd.ifq_maxlen = uimax(ifqmaxlen, NET_TX_RING_SIZE * 2); - ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; + ifp->if_capabilities = + IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx + | IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx; ifp->if_ioctl = xennetback_ifioctl; ifp->if_start = xennetback_ifstart; ifp->if_watchdog = xennetback_ifwatchdog; @@ -857,52 +859,28 @@ xennetback_evthandler(void *arg) } } -#ifdef notyet /* - * A lot of work is needed in the tcp stack to handle read-only - * ext storage so always copy for now. + * This is the last TX buffer. Copy the data and + * ack it. Delaying it until the mbuf is + * freed will stall transmit. */ - if (((req_cons + 1) & (NET_TX_RING_SIZE - 1)) == - (xneti->xni_txring.rsp_prod_pvt & (NET_TX_RING_SIZE - 1))) -#else - if (1) -#endif /* notyet */ - { - /* - * This is the last TX buffer. Copy the data and - * ack it. Delaying it until the mbuf is - * freed will stall transmit. - */ - m->m_len = uimin(MHLEN, txreq.size); - m->m_pkthdr.len = 0; - m_copyback(m, 0, txreq.size, - (void *)(pkt_va + txreq.offset)); - xni_pkt_unmap(pkt, pkt_va); - if (m->m_pkthdr.len < txreq.size) { - if_statinc(ifp, if_ierrors); - m_freem(m); - xennetback_tx_response(xneti, txreq.id, - NETIF_RSP_DROPPED); - continue; - } + m->m_len = uimin(MHLEN, txreq.size); + m->m_pkthdr.len = 0; + m_copyback(m, 0, txreq.size, + (void *)(pkt_va + txreq.offset)); + xni_pkt_unmap(pkt, pkt_va); + if (m->m_pkthdr.len < txreq.size) { + if_statinc(ifp, if_ierrors); + m_freem(m); xennetback_tx_response(xneti, txreq.id, - NETIF_RSP_OKAY); - } else { - - pkt->pkt_id = txreq.id; - pkt->pkt_xneti = xneti; - - MEXTADD(m, pkt_va + txreq.offset, - txreq.size, M_DEVBUF, xennetback_tx_free, pkt); - m->m_pkthdr.len = m->m_len = txreq.size; - m->m_flags |= M_EXT_ROMAP; + NETIF_RSP_DROPPED); + continue; } + xennetback_tx_response(xneti, txreq.id, + NETIF_RSP_OKAY); + if ((txreq.flags & NETTXF_csum_blank) != 0) { - xennet_checksum_fill(&m); - if (m == NULL) { - if_statinc(ifp, if_ierrors); - continue; - } + xennet_checksum_fill(ifp, m); } m_set_rcvif(m, ifp);