[NET] Generalise TCP's struct open_request minisock infrastructure

Kept this first changeset minimal, without changing existing names to
ease peer review.

Basicaly tcp_openreq_alloc now receives the or_calltable, that in turn
has two new members:

->slab, that replaces tcp_openreq_cachep
->obj_size, to inform the size of the openreq descendant for
  a specific protocol

The protocol specific fields in struct open_request were moved to a
class hierarchy, with the things that are common to all connection
oriented PF_INET protocols in struct inet_request_sock, the TCP ones
in tcp_request_sock, that is an inet_request_sock, that is an
open_request.

I.e. this uses the same approach used for the struct sock class
hierarchy, with sk_prot indicating if the protocol wants to use the
open_request infrastructure by filling in sk_prot->rsk_prot with an
or_calltable.

Results? Performance is improved and TCP v4 now uses only 64 bytes per
open request minisock, down from 96 without this patch :-)

Next changeset will rename some of the structs, fields and functions
mentioned above, struct or_calltable is way unclear, better name it
struct request_sock_ops, s/struct open_request/struct request_sock/g,
etc.

Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arnaldo Carvalho de Melo
2005-06-18 22:46:52 -07:00
committed by David S. Miller
parent 1944972d3b
commit 2e6599cb89
16 changed files with 341 additions and 230 deletions

View File

@@ -190,6 +190,8 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct ip_options *opt)
{
struct inet_request_sock *ireq;
struct tcp_request_sock *treq;
struct tcp_sock *tp = tcp_sk(sk);
__u32 cookie = ntohl(skb->h.th->ack_seq) - 1;
struct sock *ret = sk;
@@ -209,19 +211,20 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
req = tcp_openreq_alloc();
ret = NULL;
req = tcp_openreq_alloc(&or_ipv4); /* for safety */
if (!req)
goto out;
req->rcv_isn = htonl(skb->h.th->seq) - 1;
req->snt_isn = cookie;
ireq = inet_rsk(req);
treq = tcp_rsk(req);
treq->rcv_isn = htonl(skb->h.th->seq) - 1;
treq->snt_isn = cookie;
req->mss = mss;
req->rmt_port = skb->h.th->source;
req->af.v4_req.loc_addr = skb->nh.iph->daddr;
req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
req->class = &or_ipv4; /* for savety */
req->af.v4_req.opt = NULL;
ireq->rmt_port = skb->h.th->source;
ireq->loc_addr = skb->nh.iph->daddr;
ireq->rmt_addr = skb->nh.iph->saddr;
ireq->opt = NULL;
/* We throwed the options of the initial SYN away, so we hope
* the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -229,17 +232,15 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
if (opt && opt->optlen) {
int opt_size = sizeof(struct ip_options) + opt->optlen;
req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
if (req->af.v4_req.opt) {
if (ip_options_echo(req->af.v4_req.opt, skb)) {
kfree(req->af.v4_req.opt);
req->af.v4_req.opt = NULL;
}
ireq->opt = kmalloc(opt_size, GFP_ATOMIC);
if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) {
kfree(ireq->opt);
ireq->opt = NULL;
}
}
req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
req->wscale_ok = req->sack_ok = 0;
ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
ireq->wscale_ok = ireq->sack_ok = 0;
req->expires = 0UL;
req->retrans = 0;
@@ -253,8 +254,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = ((opt && opt->srr) ?
opt->faddr :
req->af.v4_req.rmt_addr),
.saddr = req->af.v4_req.loc_addr,
ireq->rmt_addr),
.saddr = ireq->loc_addr,
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_TCP,
.uli_u = { .ports =
@@ -272,7 +273,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
&req->rcv_wnd, &req->window_clamp,
0, &rcv_wscale);
/* BTW win scale with syncookies is 0 by definition */
req->rcv_wscale = rcv_wscale;
ireq->rcv_wscale = rcv_wscale;
ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
out: return ret;