xref: /freebsd/sys/netinet/tcp_offload.c (revision 8c6104c48ea3f0ffaabeb9784b0f2327db04e7af)
18b5709dfSKip Macy /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro F. Giffuni  *
409fe6320SNavdeep Parhar  * Copyright (c) 2012 Chelsio Communications, Inc.
58b5709dfSKip Macy  * All rights reserved.
68b5709dfSKip Macy  *
78b5709dfSKip Macy  * Redistribution and use in source and binary forms, with or without
809fe6320SNavdeep Parhar  * modification, are permitted provided that the following conditions
909fe6320SNavdeep Parhar  * are met:
1009fe6320SNavdeep Parhar  * 1. Redistributions of source code must retain the above copyright
1109fe6320SNavdeep Parhar  *    notice, this list of conditions and the following disclaimer.
1209fe6320SNavdeep Parhar  * 2. Redistributions in binary form must reproduce the above copyright
1309fe6320SNavdeep Parhar  *    notice, this list of conditions and the following disclaimer in the
1409fe6320SNavdeep Parhar  *    documentation and/or other materials provided with the distribution.
158b5709dfSKip Macy  *
1609fe6320SNavdeep Parhar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1709fe6320SNavdeep Parhar  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188b5709dfSKip Macy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1909fe6320SNavdeep Parhar  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2009fe6320SNavdeep Parhar  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2109fe6320SNavdeep Parhar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2209fe6320SNavdeep Parhar  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2309fe6320SNavdeep Parhar  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2409fe6320SNavdeep Parhar  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2509fe6320SNavdeep Parhar  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2609fe6320SNavdeep Parhar  * SUCH DAMAGE.
278b5709dfSKip Macy  */
288b5709dfSKip Macy 
298b5709dfSKip Macy #include <sys/cdefs.h>
3009fe6320SNavdeep Parhar #include "opt_inet.h"
319e88f47cSAlexander V. Chernikov #include "opt_inet6.h"
3209fe6320SNavdeep Parhar 
338b5709dfSKip Macy #include <sys/param.h>
348b5709dfSKip Macy #include <sys/systm.h>
35e2e050c8SConrad Meyer #include <sys/eventhandler.h>
368b5709dfSKip Macy #include <sys/mbuf.h>
378b5709dfSKip Macy #include <sys/socket.h>
388b5709dfSKip Macy #include <sys/socketvar.h>
3909fe6320SNavdeep Parhar #include <sys/sockopt.h>
408b5709dfSKip Macy #include <net/if.h>
4176039bc8SGleb Smirnoff #include <net/if_var.h>
423d0d5b21SJustin Hibbits #include <net/if_private.h>
435736e6fbSBjoern A. Zeeb #include <net/route.h>
448d6708baSAlexander V. Chernikov #include <net/route/nhop.h>
458b5709dfSKip Macy #include <netinet/in.h>
468b5709dfSKip Macy #include <netinet/in_pcb.h>
478d6708baSAlexander V. Chernikov #include <netinet/in_fib.h>
488d6708baSAlexander V. Chernikov #include <netinet6/in6_fib.h>
498b5709dfSKip Macy #include <netinet/tcp.h>
508b5709dfSKip Macy #include <netinet/tcp_offload.h>
51a00f4ac2SGleb Smirnoff #define	TCPOUTFLAGS
5209fe6320SNavdeep Parhar #include <netinet/tcp_fsm.h>
5357a78e3bSGleb Smirnoff #include <netinet/tcp_var.h>
5409fe6320SNavdeep Parhar #include <netinet/toecore.h>
558b5709dfSKip Macy 
5609fe6320SNavdeep Parhar int registered_toedevs;
577c80e4f3SKip Macy 
5809fe6320SNavdeep Parhar /*
5909fe6320SNavdeep Parhar  * Provide an opportunity for a TOE driver to offload.
6009fe6320SNavdeep Parhar  */
618b5709dfSKip Macy int
tcp_offload_connect(struct socket * so,struct sockaddr * nam)628b5709dfSKip Macy tcp_offload_connect(struct socket *so, struct sockaddr *nam)
638b5709dfSKip Macy {
648b5709dfSKip Macy 	struct ifnet *ifp;
6509fe6320SNavdeep Parhar 	struct toedev *tod;
668d6708baSAlexander V. Chernikov 	struct nhop_object *nh;
678d6708baSAlexander V. Chernikov 	struct epoch_tracker et;
6809fe6320SNavdeep Parhar 	int error = EOPNOTSUPP;
698b5709dfSKip Macy 
7009fe6320SNavdeep Parhar 	INP_WLOCK_ASSERT(sotoinpcb(so));
7109fe6320SNavdeep Parhar 	KASSERT(nam->sa_family == AF_INET || nam->sa_family == AF_INET6,
7209fe6320SNavdeep Parhar 	    ("%s: called with sa_family %d", __func__, nam->sa_family));
737c80e4f3SKip Macy 
7409fe6320SNavdeep Parhar 	if (registered_toedevs == 0)
7509fe6320SNavdeep Parhar 		return (error);
7609fe6320SNavdeep Parhar 
778d6708baSAlexander V. Chernikov 	NET_EPOCH_ENTER(et);
788d6708baSAlexander V. Chernikov 	nh = NULL;
799e88f47cSAlexander V. Chernikov #ifdef INET
808d6708baSAlexander V. Chernikov 	if (nam->sa_family == AF_INET)
818d6708baSAlexander V. Chernikov 		nh = fib4_lookup(0, ((struct sockaddr_in *)nam)->sin_addr,
828d6708baSAlexander V. Chernikov 		    NHR_NONE, 0, 0);
839e88f47cSAlexander V. Chernikov #endif
849e88f47cSAlexander V. Chernikov #if defined(INET) && defined(INET6)
859e88f47cSAlexander V. Chernikov 	else
869e88f47cSAlexander V. Chernikov #endif
879e88f47cSAlexander V. Chernikov #ifdef INET6
889e88f47cSAlexander V. Chernikov 	if (nam->sa_family == AF_INET6)
898d6708baSAlexander V. Chernikov 		nh = fib6_lookup(0, &((struct sockaddr_in6 *)nam)->sin6_addr,
908d6708baSAlexander V. Chernikov 		    NHR_NONE, 0, 0);
919e88f47cSAlexander V. Chernikov #endif
928d6708baSAlexander V. Chernikov 	if (nh == NULL) {
938d6708baSAlexander V. Chernikov 		NET_EPOCH_EXIT(et);
948b5709dfSKip Macy 		return (EHOSTUNREACH);
958d6708baSAlexander V. Chernikov 	}
968b5709dfSKip Macy 
978d6708baSAlexander V. Chernikov 	ifp = nh->nh_ifp;
988b5709dfSKip Macy 
9909fe6320SNavdeep Parhar 	if (nam->sa_family == AF_INET && !(ifp->if_capenable & IFCAP_TOE4))
10009fe6320SNavdeep Parhar 		goto done;
10109fe6320SNavdeep Parhar 	if (nam->sa_family == AF_INET6 && !(ifp->if_capenable & IFCAP_TOE6))
10209fe6320SNavdeep Parhar 		goto done;
1038b5709dfSKip Macy 
10409fe6320SNavdeep Parhar 	tod = TOEDEV(ifp);
10509fe6320SNavdeep Parhar 	if (tod != NULL)
1068d6708baSAlexander V. Chernikov 		error = tod->tod_connect(tod, so, nh, nam);
10709fe6320SNavdeep Parhar done:
1088d6708baSAlexander V. Chernikov 	NET_EPOCH_EXIT(et);
1098b5709dfSKip Macy 	return (error);
1108b5709dfSKip Macy }
111b1f8bd64SKip Macy 
11209fe6320SNavdeep Parhar void
tcp_offload_listen_start(struct tcpcb * tp)11309fe6320SNavdeep Parhar tcp_offload_listen_start(struct tcpcb *tp)
11409fe6320SNavdeep Parhar {
115b1f8bd64SKip Macy 
1169eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
11709fe6320SNavdeep Parhar 
11809fe6320SNavdeep Parhar 	EVENTHANDLER_INVOKE(tcp_offload_listen_start, tp);
11909fe6320SNavdeep Parhar }
120b1f8bd64SKip Macy 
121b1f8bd64SKip Macy void
tcp_offload_listen_stop(struct tcpcb * tp)12209fe6320SNavdeep Parhar tcp_offload_listen_stop(struct tcpcb *tp)
123b1f8bd64SKip Macy {
124b1f8bd64SKip Macy 
1259eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
12609fe6320SNavdeep Parhar 
12709fe6320SNavdeep Parhar 	EVENTHANDLER_INVOKE(tcp_offload_listen_stop, tp);
128b1f8bd64SKip Macy }
129b1f8bd64SKip Macy 
13009fe6320SNavdeep Parhar void
tcp_offload_input(struct tcpcb * tp,struct mbuf * m)13109fe6320SNavdeep Parhar tcp_offload_input(struct tcpcb *tp, struct mbuf *m)
132b1f8bd64SKip Macy {
13309fe6320SNavdeep Parhar 	struct toedev *tod = tp->tod;
134b1f8bd64SKip Macy 
13509fe6320SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
1369eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
137b1f8bd64SKip Macy 
13809fe6320SNavdeep Parhar 	tod->tod_input(tod, tp, m);
139b1f8bd64SKip Macy }
140b1f8bd64SKip Macy 
14109fe6320SNavdeep Parhar int
tcp_offload_output(struct tcpcb * tp)14209fe6320SNavdeep Parhar tcp_offload_output(struct tcpcb *tp)
143b1f8bd64SKip Macy {
14409fe6320SNavdeep Parhar 	struct toedev *tod = tp->tod;
14509fe6320SNavdeep Parhar 	int error, flags;
146b1f8bd64SKip Macy 
14709fe6320SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
1489eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
149b1f8bd64SKip Macy 
15009fe6320SNavdeep Parhar 	flags = tcp_outflags[tp->t_state];
15109fe6320SNavdeep Parhar 
15209fe6320SNavdeep Parhar 	if (flags & TH_RST) {
15309fe6320SNavdeep Parhar 		/* XXX: avoid repeated calls like we do for FIN */
15409fe6320SNavdeep Parhar 		error = tod->tod_send_rst(tod, tp);
15509fe6320SNavdeep Parhar 	} else if ((flags & TH_FIN || tp->t_flags & TF_NEEDFIN) &&
15609fe6320SNavdeep Parhar 	    (tp->t_flags & TF_SENTFIN) == 0) {
15709fe6320SNavdeep Parhar 		error = tod->tod_send_fin(tod, tp);
15809fe6320SNavdeep Parhar 		if (error == 0)
15909fe6320SNavdeep Parhar 			tp->t_flags |= TF_SENTFIN;
16009fe6320SNavdeep Parhar 	} else
16109fe6320SNavdeep Parhar 		error = tod->tod_output(tod, tp);
16209fe6320SNavdeep Parhar 
16309fe6320SNavdeep Parhar 	return (error);
164b1f8bd64SKip Macy }
165b1f8bd64SKip Macy 
16609fe6320SNavdeep Parhar void
tcp_offload_rcvd(struct tcpcb * tp)16709fe6320SNavdeep Parhar tcp_offload_rcvd(struct tcpcb *tp)
16809fe6320SNavdeep Parhar {
16909fe6320SNavdeep Parhar 	struct toedev *tod = tp->tod;
17009fe6320SNavdeep Parhar 
17109fe6320SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
1729eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
17309fe6320SNavdeep Parhar 
17409fe6320SNavdeep Parhar 	tod->tod_rcvd(tod, tp);
17509fe6320SNavdeep Parhar }
17609fe6320SNavdeep Parhar 
17709fe6320SNavdeep Parhar void
tcp_offload_ctloutput(struct tcpcb * tp,int sopt_dir,int sopt_name)17809fe6320SNavdeep Parhar tcp_offload_ctloutput(struct tcpcb *tp, int sopt_dir, int sopt_name)
17909fe6320SNavdeep Parhar {
18009fe6320SNavdeep Parhar 	struct toedev *tod = tp->tod;
18109fe6320SNavdeep Parhar 
18209fe6320SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
1839eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
18409fe6320SNavdeep Parhar 
18509fe6320SNavdeep Parhar 	tod->tod_ctloutput(tod, tp, sopt_dir, sopt_name);
18609fe6320SNavdeep Parhar }
18709fe6320SNavdeep Parhar 
18809fe6320SNavdeep Parhar void
tcp_offload_tcp_info(const struct tcpcb * tp,struct tcp_info * ti)189*8c6104c4SMarius Strobl tcp_offload_tcp_info(const struct tcpcb *tp, struct tcp_info *ti)
190a6456410SNavdeep Parhar {
191a6456410SNavdeep Parhar 	struct toedev *tod = tp->tod;
192a6456410SNavdeep Parhar 
193a6456410SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
194*8c6104c4SMarius Strobl 	INP_LOCK_ASSERT(tptoinpcb(tp));
195a6456410SNavdeep Parhar 
196a6456410SNavdeep Parhar 	tod->tod_tcp_info(tod, tp, ti);
197a6456410SNavdeep Parhar }
198a6456410SNavdeep Parhar 
1999e14430dSJohn Baldwin int
tcp_offload_alloc_tls_session(struct tcpcb * tp,struct ktls_session * tls,int direction)200f1f93475SJohn Baldwin tcp_offload_alloc_tls_session(struct tcpcb *tp, struct ktls_session *tls,
201f1f93475SJohn Baldwin     int direction)
2029e14430dSJohn Baldwin {
2039e14430dSJohn Baldwin 	struct toedev *tod = tp->tod;
2049e14430dSJohn Baldwin 
2059e14430dSJohn Baldwin 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
2069eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
2079e14430dSJohn Baldwin 
208f1f93475SJohn Baldwin 	return (tod->tod_alloc_tls_session(tod, tp, tls, direction));
2099e14430dSJohn Baldwin }
2109e14430dSJohn Baldwin 
211a6456410SNavdeep Parhar void
tcp_offload_detach(struct tcpcb * tp)21209fe6320SNavdeep Parhar tcp_offload_detach(struct tcpcb *tp)
21309fe6320SNavdeep Parhar {
21409fe6320SNavdeep Parhar 	struct toedev *tod = tp->tod;
21509fe6320SNavdeep Parhar 
21609fe6320SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
2179eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
21809fe6320SNavdeep Parhar 
21909fe6320SNavdeep Parhar 	tod->tod_pcb_detach(tod, tp);
22009fe6320SNavdeep Parhar }
22101d74fe1SNavdeep Parhar 
22201d74fe1SNavdeep Parhar void
tcp_offload_pmtu_update(struct tcpcb * tp,tcp_seq seq,int mtu)22301d74fe1SNavdeep Parhar tcp_offload_pmtu_update(struct tcpcb *tp, tcp_seq seq, int mtu)
22401d74fe1SNavdeep Parhar {
22501d74fe1SNavdeep Parhar 	struct toedev *tod = tp->tod;
22601d74fe1SNavdeep Parhar 
22701d74fe1SNavdeep Parhar 	KASSERT(tod != NULL, ("%s: tp->tod is NULL, tp %p", __func__, tp));
2289eb0e832SGleb Smirnoff 	INP_WLOCK_ASSERT(tptoinpcb(tp));
22901d74fe1SNavdeep Parhar 
23001d74fe1SNavdeep Parhar 	tod->tod_pmtu_update(tod, tp, seq, mtu);
23101d74fe1SNavdeep Parhar }
232