diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2011-04-26 17:51:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-04-27 16:14:04 -0400 |
commit | 9914ae3ca770389a3bec3114d0a07532a7f235dd (patch) | |
tree | 269120740aa1afdb0dd792284341aaee93024f28 /net/sctp/protocol.c | |
parent | 625034113bd45c71fb9e329f52f25fef9e6993a3 (diff) |
sctp: cache the ipv6 source after route lookup
The ipv6 routing lookup does give us a source address,
but instead of filling it into the dst, it's stored in
the flowi. We can use that instead of going through the
entire source address selection again.
Also the useless ->dst_saddr member of sctp_pf is removed.
And sctp_v6_dst_saddr() is removed, instead by introduce
sctp_v6_to_addr(), which can be reused to cleanup some dup
code.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/protocol.c')
-rw-r--r-- | net/sctp/protocol.c | 47 |
1 files changed, 22 insertions, 25 deletions
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d5bf91d04f63..34216458ded1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -465,33 +465,35 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) | |||
465 | */ | 465 | */ |
466 | static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | 466 | static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, |
467 | union sctp_addr *daddr, | 467 | union sctp_addr *daddr, |
468 | union sctp_addr *saddr) | 468 | union sctp_addr *saddr, |
469 | struct flowi *fl, | ||
470 | struct sock *sk) | ||
469 | { | 471 | { |
470 | struct rtable *rt; | 472 | struct rtable *rt; |
471 | struct flowi4 fl4; | 473 | struct flowi4 *fl4 = &fl->u.ip4; |
472 | struct sctp_bind_addr *bp; | 474 | struct sctp_bind_addr *bp; |
473 | struct sctp_sockaddr_entry *laddr; | 475 | struct sctp_sockaddr_entry *laddr; |
474 | struct dst_entry *dst = NULL; | 476 | struct dst_entry *dst = NULL; |
475 | union sctp_addr dst_saddr; | 477 | union sctp_addr dst_saddr; |
476 | 478 | ||
477 | memset(&fl4, 0x0, sizeof(struct flowi4)); | 479 | memset(fl4, 0x0, sizeof(struct flowi4)); |
478 | fl4.daddr = daddr->v4.sin_addr.s_addr; | 480 | fl4->daddr = daddr->v4.sin_addr.s_addr; |
479 | fl4.fl4_dport = daddr->v4.sin_port; | 481 | fl4->fl4_dport = daddr->v4.sin_port; |
480 | fl4.flowi4_proto = IPPROTO_SCTP; | 482 | fl4->flowi4_proto = IPPROTO_SCTP; |
481 | if (asoc) { | 483 | if (asoc) { |
482 | fl4.flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); | 484 | fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); |
483 | fl4.flowi4_oif = asoc->base.sk->sk_bound_dev_if; | 485 | fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; |
484 | fl4.fl4_sport = htons(asoc->base.bind_addr.port); | 486 | fl4->fl4_sport = htons(asoc->base.bind_addr.port); |
485 | } | 487 | } |
486 | if (saddr) { | 488 | if (saddr) { |
487 | fl4.saddr = saddr->v4.sin_addr.s_addr; | 489 | fl4->saddr = saddr->v4.sin_addr.s_addr; |
488 | fl4.fl4_sport = saddr->v4.sin_port; | 490 | fl4->fl4_sport = saddr->v4.sin_port; |
489 | } | 491 | } |
490 | 492 | ||
491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 493 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
492 | __func__, &fl4.daddr, &fl4.saddr); | 494 | __func__, &fl4->daddr, &fl4->saddr); |
493 | 495 | ||
494 | rt = ip_route_output_key(&init_net, &fl4); | 496 | rt = ip_route_output_key(&init_net, fl4); |
495 | if (!IS_ERR(rt)) | 497 | if (!IS_ERR(rt)) |
496 | dst = &rt->dst; | 498 | dst = &rt->dst; |
497 | 499 | ||
@@ -533,9 +535,9 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
533 | continue; | 535 | continue; |
534 | if ((laddr->state == SCTP_ADDR_SRC) && | 536 | if ((laddr->state == SCTP_ADDR_SRC) && |
535 | (AF_INET == laddr->a.sa.sa_family)) { | 537 | (AF_INET == laddr->a.sa.sa_family)) { |
536 | fl4.saddr = laddr->a.v4.sin_addr.s_addr; | 538 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; |
537 | fl4.fl4_sport = laddr->a.v4.sin_port; | 539 | fl4->fl4_sport = laddr->a.v4.sin_port; |
538 | rt = ip_route_output_key(&init_net, &fl4); | 540 | rt = ip_route_output_key(&init_net, fl4); |
539 | if (!IS_ERR(rt)) { | 541 | if (!IS_ERR(rt)) { |
540 | dst = &rt->dst; | 542 | dst = &rt->dst; |
541 | goto out_unlock; | 543 | goto out_unlock; |
@@ -559,19 +561,15 @@ out: | |||
559 | * to cache it separately and hence this is an empty routine. | 561 | * to cache it separately and hence this is an empty routine. |
560 | */ | 562 | */ |
561 | static void sctp_v4_get_saddr(struct sctp_sock *sk, | 563 | static void sctp_v4_get_saddr(struct sctp_sock *sk, |
562 | struct sctp_association *asoc, | 564 | struct sctp_transport *t, |
563 | struct dst_entry *dst, | ||
564 | union sctp_addr *daddr, | 565 | union sctp_addr *daddr, |
565 | union sctp_addr *saddr) | 566 | struct flowi *fl) |
566 | { | 567 | { |
567 | struct rtable *rt = (struct rtable *)dst; | 568 | union sctp_addr *saddr = &t->saddr; |
568 | 569 | struct rtable *rt = (struct rtable *)t->dst; | |
569 | if (!asoc) | ||
570 | return; | ||
571 | 570 | ||
572 | if (rt) { | 571 | if (rt) { |
573 | saddr->v4.sin_family = AF_INET; | 572 | saddr->v4.sin_family = AF_INET; |
574 | saddr->v4.sin_port = htons(asoc->base.bind_addr.port); | ||
575 | saddr->v4.sin_addr.s_addr = rt->rt_src; | 573 | saddr->v4.sin_addr.s_addr = rt->rt_src; |
576 | } | 574 | } |
577 | } | 575 | } |
@@ -950,7 +948,6 @@ static struct sctp_af sctp_af_inet = { | |||
950 | .to_sk_daddr = sctp_v4_to_sk_daddr, | 948 | .to_sk_daddr = sctp_v4_to_sk_daddr, |
951 | .from_addr_param = sctp_v4_from_addr_param, | 949 | .from_addr_param = sctp_v4_from_addr_param, |
952 | .to_addr_param = sctp_v4_to_addr_param, | 950 | .to_addr_param = sctp_v4_to_addr_param, |
953 | .dst_saddr = sctp_v4_dst_saddr, | ||
954 | .cmp_addr = sctp_v4_cmp_addr, | 951 | .cmp_addr = sctp_v4_cmp_addr, |
955 | .addr_valid = sctp_v4_addr_valid, | 952 | .addr_valid = sctp_v4_addr_valid, |
956 | .inaddr_any = sctp_v4_inaddr_any, | 953 | .inaddr_any = sctp_v4_inaddr_any, |