-/* $OpenBSD: if.h,v 1.211 2023/03/07 20:09:48 jan Exp $ */
+/* $OpenBSD: if.h,v 1.212 2023/05/15 16:34:56 bluhm Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
#define IFXF_INET6_NOSOII 0x40 /* [N] don't do RFC 7217 */
#define IFXF_AUTOCONF4 0x80 /* [N] v4 autoconf (aka dhcp) enabled */
#define IFXF_MONITOR 0x100 /* [N] only used for bpf */
-#define IFXF_TSO 0x200 /* [N] TCP segment offloading */
+#define IFXF_TSO 0x200 /* [N] XXX missnamed, should be LRO */
#define IFXF_CANTCHANGE \
(IFXF_MPSAFE|IFXF_CLONED)
#define IFCAP_VLAN_HWTAGGING 0x00000020 /* hardware VLAN tag support */
#define IFCAP_CSUM_TCPv6 0x00000080 /* can do IPv6/TCP checksums */
#define IFCAP_CSUM_UDPv6 0x00000100 /* can do IPv6/UDP checksums */
-#define IFCAP_TSO 0x00004000 /* TCP segment offloading */
+#define IFCAP_TSOv4 0x00001000 /* IPv4/TCP segment offload */
+#define IFCAP_TSOv6 0x00002000 /* IPv6/TCP segment offload */
+#define IFCAP_TSO 0x00004000 /* XXX should be LRO */
#define IFCAP_WOL 0x00008000 /* can do wake on lan */
#define IFCAP_CSUM_MASK (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | \
-/* $OpenBSD: pf.c,v 1.1179 2023/05/13 13:35:17 bluhm Exp $ */
+/* $OpenBSD: pf.c,v 1.1180 2023/05/15 16:34:56 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
goto done;
}
- if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO) &&
- m0->m_pkthdr.ph_mss <= ifp->if_mtu) {
- if (tcp_chopper(m0, &ml, ifp, m0->m_pkthdr.ph_mss) ||
- if_output_ml(ifp, &ml, sintosa(dst), rt))
- goto done;
- tcpstat_inc(tcps_outswtso);
+ if (tcp_if_output_tso(ifp, &m0, sintosa(dst), rt,
+ IFCAP_TSOv4, ifp->if_mtu) || m0 == NULL)
goto done;
- }
- CLR(m0->m_pkthdr.csum_flags, M_TCP_TSO);
/*
* Too large for interface; fragment if possible.
pf_route6(struct pf_pdesc *pd, struct pf_state *st)
{
struct mbuf *m0;
- struct mbuf_list ml;
struct sockaddr_in6 *dst, sin6;
struct rtentry *rt = NULL;
struct ip6_hdr *ip6;
goto done;
}
- if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO) &&
- m0->m_pkthdr.ph_mss <= ifp->if_mtu) {
- if (tcp_chopper(m0, &ml, ifp, m0->m_pkthdr.ph_mss) ||
- if_output_ml(ifp, &ml, sin6tosa(dst), rt))
- goto done;
- tcpstat_inc(tcps_outswtso);
+ if (tcp_if_output_tso(ifp, &m0, sin6tosa(dst), rt,
+ IFCAP_TSOv6, ifp->if_mtu) || m0 == NULL)
goto done;
- }
- CLR(m0->m_pkthdr.csum_flags, M_TCP_TSO);
ip6stat_inc(ip6s_cantfrag);
if (st->rt != PF_DUPTO)
-/* $OpenBSD: ip_output.c,v 1.386 2023/05/13 13:35:17 bluhm Exp $ */
+/* $OpenBSD: ip_output.c,v 1.387 2023/05/15 16:34:56 bluhm Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
goto done;
}
- if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) &&
- m->m_pkthdr.ph_mss <= mtu) {
- if ((error = tcp_chopper(m, &ml, ifp, m->m_pkthdr.ph_mss)) ||
- (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt)))
- goto done;
- tcpstat_inc(tcps_outswtso);
+ error = tcp_if_output_tso(ifp, &m, sintosa(dst), ro->ro_rt,
+ IFCAP_TSOv4, mtu);
+ if (error || m == NULL)
goto done;
- }
- CLR(m->m_pkthdr.csum_flags, M_TCP_TSO);
/*
* Too large for interface; fragment if possible.
u_int16_t csum = 0, offset;
offset = ip->ip_hl << 2;
- if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT))
+ if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+ csum = in_cksum_phdr(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htonl(ip->ip_p));
+ } else if (ISSET(m->m_pkthdr.csum_flags,
+ M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) {
csum = in_cksum_phdr(ip->ip_src.s_addr,
ip->ip_dst.s_addr, htonl(ntohs(ip->ip_len) -
offset + ip->ip_p));
+ }
if (ip->ip_p == IPPROTO_TCP)
offset += offsetof(struct tcphdr, th_sum);
else if (ip->ip_p == IPPROTO_UDP)
-/* $OpenBSD: tcp_output.c,v 1.137 2023/05/13 13:35:18 bluhm Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.138 2023/05/15 16:34:56 bluhm Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
#include <sys/kernel.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/route.h>
#if NPF > 0
#include <net/pfvar.h>
/* Enable TSO and specify the size of the resulting segments. */
if (tso) {
- m->m_pkthdr.csum_flags |= M_TCP_TSO;
+ SET(m->m_pkthdr.csum_flags, M_TCP_TSO);
m->m_pkthdr.ph_mss = tp->t_maxseg;
}
ml_purge(ml);
return error;
}
+
+int
+tcp_if_output_tso(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst,
+ struct rtentry *rt, uint32_t ifcap, u_int mtu)
+{
+ struct mbuf_list ml;
+ int error;
+
+ /* caller must fail later or fragment */
+ if (!ISSET((*mp)->m_pkthdr.csum_flags, M_TCP_TSO))
+ return 0;
+ if ((*mp)->m_pkthdr.ph_mss > mtu) {
+ CLR((*mp)->m_pkthdr.csum_flags, M_TCP_TSO);
+ return 0;
+ }
+
+ /* network interface hardware will do TSO */
+ if (in_ifcap_cksum(*mp, ifp, ifcap)) {
+ if (ISSET(ifcap, IFCAP_TSOv4)) {
+ in_hdr_cksum_out(*mp, ifp);
+ in_proto_cksum_out(*mp, ifp);
+ }
+#ifdef INET6
+ if (ISSET(ifcap, IFCAP_TSOv6))
+ in6_proto_cksum_out(*mp, ifp);
+#endif
+ error = ifp->if_output(ifp, *mp, dst, rt);
+ if (!error)
+ tcpstat_inc(tcps_outhwtso);
+ goto done;
+ }
+
+ /* as fallback do TSO in software */
+ if ((error = tcp_chopper(*mp, &ml, ifp, (*mp)->m_pkthdr.ph_mss)) ||
+ (error = if_output_ml(ifp, &ml, dst, rt)))
+ goto done;
+ tcpstat_inc(tcps_outswtso);
+
+ done:
+ *mp = NULL;
+ return error;
+}
-/* $OpenBSD: tcp_var.h,v 1.164 2023/05/10 12:07:16 bluhm Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.165 2023/05/15 16:34:56 bluhm Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
void tcp_notify(struct inpcb *, int);
int tcp_output(struct tcpcb *);
int tcp_chopper(struct mbuf *, struct mbuf_list *, struct ifnet *, u_int);
+int tcp_if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *,
+ struct rtentry *, uint32_t, u_int);
void tcp_pulloutofband(struct socket *, u_int, struct mbuf *, int);
int tcp_reass(struct tcpcb *, struct tcphdr *, struct mbuf *, int *);
void tcp_rscale(struct tcpcb *, u_long);
-/* $OpenBSD: ip6_output.c,v 1.275 2023/05/10 12:07:17 bluhm Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.276 2023/05/15 16:34:57 bluhm Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
goto done;
}
- if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) &&
- m->m_pkthdr.ph_mss <= mtu) {
- if ((error = tcp_chopper(m, &ml, ifp, m->m_pkthdr.ph_mss)) ||
- (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt)))
- goto done;
- tcpstat_inc(tcps_outswtso);
+ error = tcp_if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt,
+ IFCAP_TSOv6, mtu);
+ if (error || m == NULL)
goto done;
- }
- CLR(m->m_pkthdr.csum_flags, M_TCP_TSO);
/*
* try to fragment the packet. case 1-b
u_int16_t csum;
offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
- csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
- htonl(m->m_pkthdr.len - offset), htonl(nxt));
+ if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+ csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
+ htonl(0), htonl(nxt));
+ } else {
+ csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
+ htonl(m->m_pkthdr.len - offset), htonl(nxt));
+ }
if (nxt == IPPROTO_TCP)
offset += offsetof(struct tcphdr, th_sum);
else if (nxt == IPPROTO_UDP)