tcp_offload.c revision 183550
1178476Sjb/*-
2178476Sjb * Copyright (c) 2007, Chelsio Inc.
3178476Sjb * All rights reserved.
4178476Sjb *
5178476Sjb * Redistribution and use in source and binary forms, with or without
6178476Sjb * modification, are permitted provided that the following conditions are met:
7178476Sjb *
8178476Sjb * 1. Redistributions of source code must retain the above copyright notice,
9178476Sjb *    this list of conditions and the following disclaimer.
10178476Sjb *
11178476Sjb * 2. Neither the name of the Chelsio Corporation nor the names of its
12178476Sjb *    contributors may be used to endorse or promote products derived from
13178476Sjb *    this software without specific prior written permission.
14178476Sjb *
15178476Sjb * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16178476Sjb * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17178476Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18178476Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19178476Sjb * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20178476Sjb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21178476Sjb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22178476Sjb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23178476Sjb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24178476Sjb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25178476Sjb * POSSIBILITY OF SUCH DAMAGE.
26178476Sjb */
27178476Sjb
28178476Sjb#include <sys/cdefs.h>
29178476Sjb__FBSDID("$FreeBSD: head/sys/netinet/tcp_offload.c 183550 2008-10-02 15:37:58Z zec $");
30178476Sjb
31178476Sjb#include <sys/param.h>
32178476Sjb#include <sys/systm.h>
33178476Sjb#include <sys/types.h>
34178476Sjb#include <sys/malloc.h>
35178476Sjb#include <sys/kernel.h>
36178476Sjb#include <sys/sysctl.h>
37178476Sjb#include <sys/mbuf.h>
38178476Sjb#include <sys/socket.h>
39178476Sjb#include <sys/socketvar.h>
40178476Sjb#include <sys/vimage.h>
41178476Sjb
42178476Sjb#include <net/if.h>
43178476Sjb#include <net/if_types.h>
44178476Sjb#include <net/if_var.h>
45178476Sjb
46178476Sjb#include <netinet/in.h>
47178476Sjb#include <netinet/in_systm.h>
48178476Sjb#include <netinet/in_pcb.h>
49178476Sjb#include <netinet/tcp.h>
50178476Sjb#include <netinet/tcp_var.h>
51178476Sjb#include <netinet/tcp_offload.h>
52178476Sjb#include <netinet/toedev.h>
53178476Sjb
54178476Sjbuint32_t toedev_registration_count;
55178476Sjb
56178476Sjbint
57tcp_offload_connect(struct socket *so, struct sockaddr *nam)
58{
59	struct ifnet *ifp;
60	struct toedev *tdev;
61	struct rtentry *rt;
62	int error;
63
64	if (toedev_registration_count == 0)
65		return (EINVAL);
66
67	/*
68	 * Look up the route used for the connection to
69	 * determine if it uses an interface capable of
70	 * offloading the connection.
71	 */
72	rt = rtalloc1(nam, 0 /*report*/, 0 /*ignflags*/);
73	if (rt)
74		RT_UNLOCK(rt);
75	else
76		return (EHOSTUNREACH);
77
78	ifp = rt->rt_ifp;
79	if ((ifp->if_capenable & IFCAP_TOE) == 0) {
80		error = EINVAL;
81		goto fail;
82	}
83
84	tdev = TOEDEV(ifp);
85	if (tdev == NULL) {
86		error = EPERM;
87		goto fail;
88	}
89
90	if (tdev->tod_can_offload(tdev, so) == 0) {
91		error = EPERM;
92		goto fail;
93	}
94
95	return (tdev->tod_connect(tdev, so, rt, nam));
96fail:
97	RTFREE(rt);
98	return (error);
99}
100
101
102/*
103 * This file contains code as a short-term staging area before it is moved in
104 * to sys/netinet/tcp_offload.c
105 */
106
107void
108tcp_offload_twstart(struct tcpcb *tp)
109{
110	INIT_VNET_INET(curvnet);
111
112	INP_INFO_WLOCK(&V_tcbinfo);
113	INP_WLOCK(tp->t_inpcb);
114	tcp_twstart(tp);
115	INP_INFO_WUNLOCK(&V_tcbinfo);
116}
117
118struct tcpcb *
119tcp_offload_close(struct tcpcb *tp)
120{
121	INIT_VNET_INET(curvnet);
122
123	INP_INFO_WLOCK(&V_tcbinfo);
124	INP_WLOCK(tp->t_inpcb);
125	tp = tcp_close(tp);
126	INP_INFO_WUNLOCK(&V_tcbinfo);
127	if (tp)
128		INP_WUNLOCK(tp->t_inpcb);
129
130	return (tp);
131}
132
133struct tcpcb *
134tcp_offload_drop(struct tcpcb *tp, int error)
135{
136	INIT_VNET_INET(curvnet);
137
138	INP_INFO_WLOCK(&V_tcbinfo);
139	INP_WLOCK(tp->t_inpcb);
140	tp = tcp_drop(tp, error);
141	INP_INFO_WUNLOCK(&V_tcbinfo);
142	if (tp)
143		INP_WUNLOCK(tp->t_inpcb);
144
145	return (tp);
146}
147
148