tcp_offload.c revision 180674
1194676Sthompsa/*-
2194676Sthompsa * Copyright (c) 2007, Chelsio Inc.
3194676Sthompsa * All rights reserved.
4195957Salfred *
5194676Sthompsa * Redistribution and use in source and binary forms, with or without
6194676Sthompsa * modification, are permitted provided that the following conditions are met:
7194676Sthompsa *
8194676Sthompsa * 1. Redistributions of source code must retain the above copyright notice,
9194676Sthompsa *    this list of conditions and the following disclaimer.
10194676Sthompsa *
11194676Sthompsa * 2. Neither the name of the Chelsio Corporation nor the names of its
12194676Sthompsa *    contributors may be used to endorse or promote products derived from
13194676Sthompsa *    this software without specific prior written permission.
14194676Sthompsa *
15194676Sthompsa * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16194676Sthompsa * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18194676Sthompsa * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19194676Sthompsa * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20194676Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21194676Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22194676Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23194676Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24194676Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25194676Sthompsa * POSSIBILITY OF SUCH DAMAGE.
26194676Sthompsa */
27194676Sthompsa
28194676Sthompsa#include <sys/cdefs.h>
29194676Sthompsa__FBSDID("$FreeBSD: head/sys/netinet/tcp_offload.c 180674 2008-07-21 21:22:56Z kmacy $");
30194676Sthompsa
31194676Sthompsa#include <sys/param.h>
32194676Sthompsa#include <sys/systm.h>
33194676Sthompsa#include <sys/types.h>
34194676Sthompsa#include <sys/malloc.h>
35195957Salfred#include <sys/kernel.h>
36195957Salfred#include <sys/sysctl.h>
37195957Salfred#include <sys/mbuf.h>
38199055Sthompsa#include <sys/socket.h>
39194676Sthompsa#include <sys/socketvar.h>
40194676Sthompsa
41194676Sthompsa#include <net/if.h>
42194676Sthompsa#include <net/if_types.h>
43194676Sthompsa#include <net/if_var.h>
44194676Sthompsa
45194676Sthompsa#include <netinet/in.h>
46194676Sthompsa#include <netinet/in_systm.h>
47194676Sthompsa#include <netinet/in_pcb.h>
48194676Sthompsa#include <netinet/tcp.h>
49195957Salfred#include <netinet/tcp_var.h>
50195957Salfred#include <netinet/tcp_offload.h>
51195957Salfred#include <netinet/toedev.h>
52195957Salfred
53195957Salfredint
54195957Salfredtcp_offload_connect(struct socket *so, struct sockaddr *nam)
55195957Salfred{
56195957Salfred	struct ifnet *ifp;
57195957Salfred	struct toedev *tdev;
58195957Salfred	struct rtentry *rt;
59195957Salfred	int error;
60195957Salfred
61194676Sthompsa	/*
62194676Sthompsa	 * Look up the route used for the connection to
63194676Sthompsa	 * determine if it uses an interface capable of
64195957Salfred	 * offloading the connection.
65194676Sthompsa	 */
66195957Salfred	rt = rtalloc1(nam, 1 /*report*/, 0 /*ignflags*/);
67194676Sthompsa	if (rt)
68194676Sthompsa		RT_UNLOCK(rt);
69194676Sthompsa	else
70194676Sthompsa		return (EHOSTUNREACH);
71194676Sthompsa
72195957Salfred	ifp = rt->rt_ifp;
73194676Sthompsa	if ((ifp->if_capenable & IFCAP_TOE) == 0) {
74194676Sthompsa		error = EINVAL;
75195957Salfred		goto fail;
76194676Sthompsa	}
77194676Sthompsa
78194676Sthompsa	tdev = TOEDEV(ifp);
79194676Sthompsa	if (tdev == NULL) {
80194676Sthompsa		error = EPERM;
81194676Sthompsa		goto fail;
82194676Sthompsa	}
83194676Sthompsa
84194676Sthompsa	if (tdev->tod_can_offload(tdev, so) == 0) {
85194676Sthompsa		error = EPERM;
86194676Sthompsa		goto fail;
87194676Sthompsa	}
88194676Sthompsa
89194676Sthompsa	return (tdev->tod_connect(tdev, so, rt, nam));
90195957Salfredfail:
91195957Salfred	RTFREE(rt);
92194676Sthompsa	return (error);
93195957Salfred}
94195957Salfred
95194676Sthompsa
96195957Salfred/*
97194676Sthompsa * This file contains code as a short-term staging area before it is moved in
98194676Sthompsa * to sys/netinet/tcp_offload.c
99194676Sthompsa */
100195957Salfred
101195957Salfredvoid
102194676Sthompsatcp_offload_twstart(struct tcpcb *tp)
103194676Sthompsa{
104194676Sthompsa
105195957Salfred	INP_INFO_WLOCK(&tcbinfo);
106195957Salfred	INP_WLOCK(tp->t_inpcb);
107195957Salfred	tcp_twstart(tp);
108195957Salfred	INP_INFO_WUNLOCK(&tcbinfo);
109195957Salfred}
110194676Sthompsa
111195957Salfredstruct tcpcb *
112194676Sthompsatcp_offload_close(struct tcpcb *tp)
113194676Sthompsa{
114194676Sthompsa
115194676Sthompsa	INP_INFO_WLOCK(&tcbinfo);
116194676Sthompsa	INP_WLOCK(tp->t_inpcb);
117194676Sthompsa	tp = tcp_close(tp);
118194676Sthompsa	INP_INFO_WUNLOCK(&tcbinfo);
119194676Sthompsa	if (tp)
120194676Sthompsa		INP_WUNLOCK(tp->t_inpcb);
121194676Sthompsa
122195957Salfred	return (tp);
123195957Salfred}
124194676Sthompsa
125194676Sthompsastruct tcpcb *
126194676Sthompsatcp_offload_drop(struct tcpcb *tp, int error)
127194676Sthompsa{
128195957Salfred
129194676Sthompsa	INP_INFO_WLOCK(&tcbinfo);
130195957Salfred	INP_WLOCK(tp->t_inpcb);
131194676Sthompsa	tp = tcp_drop(tp, error);
132195957Salfred	INP_INFO_WUNLOCK(&tcbinfo);
133195957Salfred	if (tp)
134195957Salfred		INP_WUNLOCK(tp->t_inpcb);
135195957Salfred
136195957Salfred	return (tp);
137195957Salfred}
138194676Sthompsa
139194676Sthompsa