diff options
author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-06-19 01:46:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-19 01:46:52 -0400 |
commit | 2e6599cb899ba4b133f42cbf9d2b1883d2dc583a (patch) | |
tree | b5d4fcca4d2a515fc3d3d20cefaaeebd8dbf661f /net/ipv4/tcp_ipv4.c | |
parent | 1944972d3bb651474a5021c9da8d0166ae19f1eb (diff) |
[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>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dad98e4a5043..e156be90df14 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -880,9 +880,11 @@ static struct open_request *tcp_v4_search_req(struct tcp_sock *tp, | |||
880 | for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)]; | 880 | for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)]; |
881 | (req = *prev) != NULL; | 881 | (req = *prev) != NULL; |
882 | prev = &req->dl_next) { | 882 | prev = &req->dl_next) { |
883 | if (req->rmt_port == rport && | 883 | const struct inet_request_sock *ireq = inet_rsk(req); |
884 | req->af.v4_req.rmt_addr == raddr && | 884 | |
885 | req->af.v4_req.loc_addr == laddr && | 885 | if (ireq->rmt_port == rport && |
886 | ireq->rmt_addr == raddr && | ||
887 | ireq->loc_addr == laddr && | ||
886 | TCP_INET_FAMILY(req->class->family)) { | 888 | TCP_INET_FAMILY(req->class->family)) { |
887 | BUG_TRAP(!req->sk); | 889 | BUG_TRAP(!req->sk); |
888 | *prevp = prev; | 890 | *prevp = prev; |
@@ -897,7 +899,7 @@ static void tcp_v4_synq_add(struct sock *sk, struct open_request *req) | |||
897 | { | 899 | { |
898 | struct tcp_sock *tp = tcp_sk(sk); | 900 | struct tcp_sock *tp = tcp_sk(sk); |
899 | struct tcp_listen_opt *lopt = tp->listen_opt; | 901 | struct tcp_listen_opt *lopt = tp->listen_opt; |
900 | u32 h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port, lopt->hash_rnd); | 902 | u32 h = tcp_v4_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd); |
901 | 903 | ||
902 | req->expires = jiffies + TCP_TIMEOUT_INIT; | 904 | req->expires = jiffies + TCP_TIMEOUT_INIT; |
903 | req->retrans = 0; | 905 | req->retrans = 0; |
@@ -1065,7 +1067,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
1065 | */ | 1067 | */ |
1066 | BUG_TRAP(!req->sk); | 1068 | BUG_TRAP(!req->sk); |
1067 | 1069 | ||
1068 | if (seq != req->snt_isn) { | 1070 | if (seq != tcp_rsk(req)->snt_isn) { |
1069 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); | 1071 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); |
1070 | goto out; | 1072 | goto out; |
1071 | } | 1073 | } |
@@ -1256,7 +1258,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1256 | 1258 | ||
1257 | static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req) | 1259 | static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req) |
1258 | { | 1260 | { |
1259 | tcp_v4_send_ack(skb, req->snt_isn + 1, req->rcv_isn + 1, req->rcv_wnd, | 1261 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
1260 | req->ts_recent); | 1262 | req->ts_recent); |
1261 | } | 1263 | } |
1262 | 1264 | ||
@@ -1264,18 +1266,19 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk, | |||
1264 | struct open_request *req) | 1266 | struct open_request *req) |
1265 | { | 1267 | { |
1266 | struct rtable *rt; | 1268 | struct rtable *rt; |
1267 | struct ip_options *opt = req->af.v4_req.opt; | 1269 | const struct inet_request_sock *ireq = inet_rsk(req); |
1270 | struct ip_options *opt = inet_rsk(req)->opt; | ||
1268 | struct flowi fl = { .oif = sk->sk_bound_dev_if, | 1271 | struct flowi fl = { .oif = sk->sk_bound_dev_if, |
1269 | .nl_u = { .ip4_u = | 1272 | .nl_u = { .ip4_u = |
1270 | { .daddr = ((opt && opt->srr) ? | 1273 | { .daddr = ((opt && opt->srr) ? |
1271 | opt->faddr : | 1274 | opt->faddr : |
1272 | req->af.v4_req.rmt_addr), | 1275 | ireq->rmt_addr), |
1273 | .saddr = req->af.v4_req.loc_addr, | 1276 | .saddr = ireq->loc_addr, |
1274 | .tos = RT_CONN_FLAGS(sk) } }, | 1277 | .tos = RT_CONN_FLAGS(sk) } }, |
1275 | .proto = IPPROTO_TCP, | 1278 | .proto = IPPROTO_TCP, |
1276 | .uli_u = { .ports = | 1279 | .uli_u = { .ports = |
1277 | { .sport = inet_sk(sk)->sport, | 1280 | { .sport = inet_sk(sk)->sport, |
1278 | .dport = req->rmt_port } } }; | 1281 | .dport = ireq->rmt_port } } }; |
1279 | 1282 | ||
1280 | if (ip_route_output_flow(&rt, &fl, sk, 0)) { | 1283 | if (ip_route_output_flow(&rt, &fl, sk, 0)) { |
1281 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | 1284 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); |
@@ -1297,6 +1300,7 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk, | |||
1297 | static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, | 1300 | static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, |
1298 | struct dst_entry *dst) | 1301 | struct dst_entry *dst) |
1299 | { | 1302 | { |
1303 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
1300 | int err = -1; | 1304 | int err = -1; |
1301 | struct sk_buff * skb; | 1305 | struct sk_buff * skb; |
1302 | 1306 | ||
@@ -1310,14 +1314,14 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, | |||
1310 | struct tcphdr *th = skb->h.th; | 1314 | struct tcphdr *th = skb->h.th; |
1311 | 1315 | ||
1312 | th->check = tcp_v4_check(th, skb->len, | 1316 | th->check = tcp_v4_check(th, skb->len, |
1313 | req->af.v4_req.loc_addr, | 1317 | ireq->loc_addr, |
1314 | req->af.v4_req.rmt_addr, | 1318 | ireq->rmt_addr, |
1315 | csum_partial((char *)th, skb->len, | 1319 | csum_partial((char *)th, skb->len, |
1316 | skb->csum)); | 1320 | skb->csum)); |
1317 | 1321 | ||
1318 | err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr, | 1322 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, |
1319 | req->af.v4_req.rmt_addr, | 1323 | ireq->rmt_addr, |
1320 | req->af.v4_req.opt); | 1324 | ireq->opt); |
1321 | if (err == NET_XMIT_CN) | 1325 | if (err == NET_XMIT_CN) |
1322 | err = 0; | 1326 | err = 0; |
1323 | } | 1327 | } |
@@ -1332,8 +1336,8 @@ out: | |||
1332 | */ | 1336 | */ |
1333 | static void tcp_v4_or_free(struct open_request *req) | 1337 | static void tcp_v4_or_free(struct open_request *req) |
1334 | { | 1338 | { |
1335 | if (req->af.v4_req.opt) | 1339 | if (inet_rsk(req)->opt) |
1336 | kfree(req->af.v4_req.opt); | 1340 | kfree(inet_rsk(req)->opt); |
1337 | } | 1341 | } |
1338 | 1342 | ||
1339 | static inline void syn_flood_warning(struct sk_buff *skb) | 1343 | static inline void syn_flood_warning(struct sk_buff *skb) |
@@ -1387,6 +1391,7 @@ int sysctl_max_syn_backlog = 256; | |||
1387 | 1391 | ||
1388 | struct or_calltable or_ipv4 = { | 1392 | struct or_calltable or_ipv4 = { |
1389 | .family = PF_INET, | 1393 | .family = PF_INET, |
1394 | .obj_size = sizeof(struct tcp_request_sock), | ||
1390 | .rtx_syn_ack = tcp_v4_send_synack, | 1395 | .rtx_syn_ack = tcp_v4_send_synack, |
1391 | .send_ack = tcp_v4_or_send_ack, | 1396 | .send_ack = tcp_v4_or_send_ack, |
1392 | .destructor = tcp_v4_or_free, | 1397 | .destructor = tcp_v4_or_free, |
@@ -1395,6 +1400,7 @@ struct or_calltable or_ipv4 = { | |||
1395 | 1400 | ||
1396 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1401 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
1397 | { | 1402 | { |
1403 | struct inet_request_sock *ireq; | ||
1398 | struct tcp_options_received tmp_opt; | 1404 | struct tcp_options_received tmp_opt; |
1399 | struct open_request *req; | 1405 | struct open_request *req; |
1400 | __u32 saddr = skb->nh.iph->saddr; | 1406 | __u32 saddr = skb->nh.iph->saddr; |
@@ -1433,7 +1439,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1433 | if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1) | 1439 | if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1) |
1434 | goto drop; | 1440 | goto drop; |
1435 | 1441 | ||
1436 | req = tcp_openreq_alloc(); | 1442 | req = tcp_openreq_alloc(&or_ipv4); |
1437 | if (!req) | 1443 | if (!req) |
1438 | goto drop; | 1444 | goto drop; |
1439 | 1445 | ||
@@ -1461,10 +1467,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1461 | 1467 | ||
1462 | tcp_openreq_init(req, &tmp_opt, skb); | 1468 | tcp_openreq_init(req, &tmp_opt, skb); |
1463 | 1469 | ||
1464 | req->af.v4_req.loc_addr = daddr; | 1470 | ireq = inet_rsk(req); |
1465 | req->af.v4_req.rmt_addr = saddr; | 1471 | ireq->loc_addr = daddr; |
1466 | req->af.v4_req.opt = tcp_v4_save_options(sk, skb); | 1472 | ireq->rmt_addr = saddr; |
1467 | req->class = &or_ipv4; | 1473 | ireq->opt = tcp_v4_save_options(sk, skb); |
1468 | if (!want_cookie) | 1474 | if (!want_cookie) |
1469 | TCP_ECN_create_request(req, skb->h.th); | 1475 | TCP_ECN_create_request(req, skb->h.th); |
1470 | 1476 | ||
@@ -1523,7 +1529,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1523 | 1529 | ||
1524 | isn = tcp_v4_init_sequence(sk, skb); | 1530 | isn = tcp_v4_init_sequence(sk, skb); |
1525 | } | 1531 | } |
1526 | req->snt_isn = isn; | 1532 | tcp_rsk(req)->snt_isn = isn; |
1527 | 1533 | ||
1528 | if (tcp_v4_send_synack(sk, req, dst)) | 1534 | if (tcp_v4_send_synack(sk, req, dst)) |
1529 | goto drop_and_free; | 1535 | goto drop_and_free; |
@@ -1551,6 +1557,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1551 | struct open_request *req, | 1557 | struct open_request *req, |
1552 | struct dst_entry *dst) | 1558 | struct dst_entry *dst) |
1553 | { | 1559 | { |
1560 | struct inet_request_sock *ireq; | ||
1554 | struct inet_sock *newinet; | 1561 | struct inet_sock *newinet; |
1555 | struct tcp_sock *newtp; | 1562 | struct tcp_sock *newtp; |
1556 | struct sock *newsk; | 1563 | struct sock *newsk; |
@@ -1570,11 +1577,12 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1570 | 1577 | ||
1571 | newtp = tcp_sk(newsk); | 1578 | newtp = tcp_sk(newsk); |
1572 | newinet = inet_sk(newsk); | 1579 | newinet = inet_sk(newsk); |
1573 | newinet->daddr = req->af.v4_req.rmt_addr; | 1580 | ireq = inet_rsk(req); |
1574 | newinet->rcv_saddr = req->af.v4_req.loc_addr; | 1581 | newinet->daddr = ireq->rmt_addr; |
1575 | newinet->saddr = req->af.v4_req.loc_addr; | 1582 | newinet->rcv_saddr = ireq->loc_addr; |
1576 | newinet->opt = req->af.v4_req.opt; | 1583 | newinet->saddr = ireq->loc_addr; |
1577 | req->af.v4_req.opt = NULL; | 1584 | newinet->opt = ireq->opt; |
1585 | ireq->opt = NULL; | ||
1578 | newinet->mc_index = tcp_v4_iif(skb); | 1586 | newinet->mc_index = tcp_v4_iif(skb); |
1579 | newinet->mc_ttl = skb->nh.iph->ttl; | 1587 | newinet->mc_ttl = skb->nh.iph->ttl; |
1580 | newtp->ext_header_len = 0; | 1588 | newtp->ext_header_len = 0; |
@@ -2454,15 +2462,16 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo) | |||
2454 | static void get_openreq4(struct sock *sk, struct open_request *req, | 2462 | static void get_openreq4(struct sock *sk, struct open_request *req, |
2455 | char *tmpbuf, int i, int uid) | 2463 | char *tmpbuf, int i, int uid) |
2456 | { | 2464 | { |
2465 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
2457 | int ttd = req->expires - jiffies; | 2466 | int ttd = req->expires - jiffies; |
2458 | 2467 | ||
2459 | sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" | 2468 | sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" |
2460 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p", | 2469 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p", |
2461 | i, | 2470 | i, |
2462 | req->af.v4_req.loc_addr, | 2471 | ireq->loc_addr, |
2463 | ntohs(inet_sk(sk)->sport), | 2472 | ntohs(inet_sk(sk)->sport), |
2464 | req->af.v4_req.rmt_addr, | 2473 | ireq->rmt_addr, |
2465 | ntohs(req->rmt_port), | 2474 | ntohs(ireq->rmt_port), |
2466 | TCP_SYN_RECV, | 2475 | TCP_SYN_RECV, |
2467 | 0, 0, /* could print option size, but that is af dependent. */ | 2476 | 0, 0, /* could print option size, but that is af dependent. */ |
2468 | 1, /* timers active (only the expire timer) */ | 2477 | 1, /* timers active (only the expire timer) */ |
@@ -2618,6 +2627,7 @@ struct proto tcp_prot = { | |||
2618 | .sysctl_rmem = sysctl_tcp_rmem, | 2627 | .sysctl_rmem = sysctl_tcp_rmem, |
2619 | .max_header = MAX_TCP_HEADER, | 2628 | .max_header = MAX_TCP_HEADER, |
2620 | .obj_size = sizeof(struct tcp_sock), | 2629 | .obj_size = sizeof(struct tcp_sock), |
2630 | .rsk_prot = &or_ipv4, | ||
2621 | }; | 2631 | }; |
2622 | 2632 | ||
2623 | 2633 | ||