aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-06-19 01:46:52 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-19 01:46:52 -0400
commit2e6599cb899ba4b133f42cbf9d2b1883d2dc583a (patch)
treeb5d4fcca4d2a515fc3d3d20cefaaeebd8dbf661f /net/ipv4/tcp_ipv4.c
parent1944972d3bb651474a5021c9da8d0166ae19f1eb (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.c72
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
1257static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req) 1259static 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,
1297static int tcp_v4_send_synack(struct sock *sk, struct open_request *req, 1300static 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 */
1333static void tcp_v4_or_free(struct open_request *req) 1337static 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
1339static inline void syn_flood_warning(struct sk_buff *skb) 1343static inline void syn_flood_warning(struct sk_buff *skb)
@@ -1387,6 +1391,7 @@ int sysctl_max_syn_backlog = 256;
1387 1391
1388struct or_calltable or_ipv4 = { 1392struct 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
1396int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 1401int 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)
2454static void get_openreq4(struct sock *sk, struct open_request *req, 2462static 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