diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-03-20 11:55:11 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-03-20 11:55:11 +0000 |
commit | 1ac443066cace32e20cc35cbbc3164263e117bb9 (patch) | |
tree | 7860cecad1d7226689ec403bcf9de35c5c8fcc82 /sys/dev | |
parent | 3431604482aebe678d10072551f483ee21d56cb4 (diff) |
some re(4) chips can do jumbos, but none of them can checksum jumbo
packets.
rather than disable cksum offload for all packets, this sets things
up so we still advertise offload to the stack, but if the driver
gets a large packet it does the checksum itself in software.
small (normal sized) packets still get offloaded like now. if you're
doing a jumbo you'll be doing the cksum in software, but will
hopefully win overall cos you'll be doing a 6th of the work cos
you're doing more data in every packet.
diff from jim smith
ok sthen@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/re.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index 51045cd3706..8ad15ce2d02 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.175 2015/02/09 03:09:57 dlg Exp $ */ +/* $OpenBSD: re.c,v 1.176 2015/03/20 11:55:10 dlg Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -128,6 +128,8 @@ #include <net/if_media.h> #include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> #include <netinet/if_ether.h> #if NVLAN > 0 @@ -194,6 +196,8 @@ void re_setup_intr(struct rl_softc *, int, int); int re_wol(struct ifnet*, int); #endif +void in_delayed_cksum(struct mbuf *); + struct cfdriver re_cd = { 0, "re", DV_IFNET }; @@ -1601,7 +1605,10 @@ int re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) { bus_dmamap_t map; + struct mbuf *mp, mh; int error, seg, nsegs, uidx, startidx, curidx, lastidx, pad; + int off; + struct ip *ip; struct rl_desc *d; u_int32_t cmdstat, vlanctl = 0, csum_flags = 0; struct rl_txq *txq; @@ -1619,6 +1626,27 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx) * RL_TDESC_CMD_UDPCSUM does not take affect. */ + if ((sc->rl_flags & RL_FLAG_JUMBOV2) && + m->m_pkthdr.len > RL_MTU && + (m->m_pkthdr.csum_flags & + (M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) != 0) { + mp = m_getptr(m, ETHER_HDR_LEN, &off); + mh.m_flags = 0; + mh.m_data = mtod(mp, caddr_t) + off; + mh.m_next = mp->m_next; + mh.m_pkthdr.len = mp->m_pkthdr.len - ETHER_HDR_LEN; + mh.m_len = mp->m_len - off; + ip = (struct ip *)mh.m_data; + + if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) + ip->ip_sum = in_cksum(&mh, sizeof(struct ip)); + if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) + in_delayed_cksum(&mh); + + m->m_pkthdr.csum_flags &= + ~(M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT); + } + if ((m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) != 0) { if (sc->rl_flags & RL_FLAG_DESCV2) { |