aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-06-09 04:25:47 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-09 04:25:47 -0400
commit4670fd819e7f47392c7c6fc6168ea2857c66d163 (patch)
treeb8e90a8a449c0b42b77b54313683ab2d0edb09f3
parentfbfe95a42e90b3dd079cc9019ba7d7700feee0f6 (diff)
tcp: Get rid of inetpeer special cases.
The get_peer method TCP uses is full of special cases that make no sense accommodating, and it also gets in the way of doing more reasonable things here. First of all, if the socket doesn't have a usable cached route, there is no sense in trying to optimize timewait recycling. Likewise for the case where we have IP options, such as SRR enabled, that make the IP header destination address (and thus the destination address of the route key) differ from that of the connection's destination address. Just return a NULL peer in these cases, and thus we're also able to get rid of the clumsy inetpeer release logic. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/inet_connection_sock.h2
-rw-r--r--include/net/tcp.h2
-rw-r--r--net/ipv4/tcp_ipv4.c21
-rw-r--r--net/ipv4/tcp_minisocks.c5
-rw-r--r--net/ipv6/tcp_ipv6.c21
5 files changed, 19 insertions, 32 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 7d83f90f203f..e1b7734c456f 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -43,7 +43,7 @@ struct inet_connection_sock_af_ops {
43 struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, 43 struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
44 struct request_sock *req, 44 struct request_sock *req,
45 struct dst_entry *dst); 45 struct dst_entry *dst);
46 struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it); 46 struct inet_peer *(*get_peer)(struct sock *sk);
47 u16 net_header_len; 47 u16 net_header_len;
48 u16 net_frag_header_len; 48 u16 net_frag_header_len;
49 u16 sockaddr_len; 49 u16 sockaddr_len;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e79aa48d9fc1..424591866037 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -327,7 +327,7 @@ extern void tcp_shutdown (struct sock *sk, int how);
327 327
328extern int tcp_v4_rcv(struct sk_buff *skb); 328extern int tcp_v4_rcv(struct sk_buff *skb);
329 329
330extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it); 330extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
331extern void *tcp_v4_tw_get_peer(struct sock *sk); 331extern void *tcp_v4_tw_get_peer(struct sock *sk);
332extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); 332extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
333extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 333extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 833e8d96a636..77f049d00dbb 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1820,23 +1820,18 @@ do_time_wait:
1820 goto discard_it; 1820 goto discard_it;
1821} 1821}
1822 1822
1823struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it) 1823struct inet_peer *tcp_v4_get_peer(struct sock *sk)
1824{ 1824{
1825 struct rtable *rt = (struct rtable *) __sk_dst_get(sk); 1825 struct rtable *rt = (struct rtable *) __sk_dst_get(sk);
1826 struct inet_sock *inet = inet_sk(sk); 1826 struct inet_sock *inet = inet_sk(sk);
1827 struct net *net = sock_net(sk);
1828 struct inet_peer *peer;
1829
1830 if (!rt ||
1831 inet->cork.fl.u.ip4.daddr != inet->inet_daddr) {
1832 peer = inet_getpeer_v4(net, inet->inet_daddr, 1);
1833 *release_it = true;
1834 } else {
1835 peer = rt_get_peer_create(rt, inet->inet_daddr);
1836 *release_it = false;
1837 }
1838 1827
1839 return peer; 1828 /* If we don't have a valid cached route, or we're doing IP
1829 * options which make the IPv4 header destination address
1830 * different from our peer's, do not bother with this.
1831 */
1832 if (!rt || inet->cork.fl.u.ip4.daddr != inet->inet_daddr)
1833 return NULL;
1834 return rt_get_peer_create(rt, inet->inet_daddr);
1840} 1835}
1841EXPORT_SYMBOL(tcp_v4_get_peer); 1836EXPORT_SYMBOL(tcp_v4_get_peer);
1842 1837
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b85d9fe7d663..fef9dbf3af00 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -60,9 +60,8 @@ static bool tcp_remember_stamp(struct sock *sk)
60 const struct inet_connection_sock *icsk = inet_csk(sk); 60 const struct inet_connection_sock *icsk = inet_csk(sk);
61 struct tcp_sock *tp = tcp_sk(sk); 61 struct tcp_sock *tp = tcp_sk(sk);
62 struct inet_peer *peer; 62 struct inet_peer *peer;
63 bool release_it;
64 63
65 peer = icsk->icsk_af_ops->get_peer(sk, &release_it); 64 peer = icsk->icsk_af_ops->get_peer(sk);
66 if (peer) { 65 if (peer) {
67 if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 || 66 if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
68 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && 67 ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
@@ -70,8 +69,6 @@ static bool tcp_remember_stamp(struct sock *sk)
70 peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp; 69 peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;
71 peer->tcp_ts = tp->rx_opt.ts_recent; 70 peer->tcp_ts = tp->rx_opt.ts_recent;
72 } 71 }
73 if (release_it)
74 inet_putpeer(peer);
75 return true; 72 return true;
76 } 73 }
77 74
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 218433cb9928..b5ecf37b61a6 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1732,23 +1732,18 @@ do_time_wait:
1732 goto discard_it; 1732 goto discard_it;
1733} 1733}
1734 1734
1735static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it) 1735static struct inet_peer *tcp_v6_get_peer(struct sock *sk)
1736{ 1736{
1737 struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk); 1737 struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk);
1738 struct ipv6_pinfo *np = inet6_sk(sk); 1738 struct ipv6_pinfo *np = inet6_sk(sk);
1739 struct net *net = sock_net(sk);
1740 struct inet_peer *peer;
1741
1742 if (!rt ||
1743 !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr)) {
1744 peer = inet_getpeer_v6(net, &np->daddr, 1);
1745 *release_it = true;
1746 } else {
1747 peer = rt6_get_peer_create(rt);
1748 *release_it = false;
1749 }
1750 1739
1751 return peer; 1740 /* If we don't have a valid cached route, or we're doing IP
1741 * options which make the IPv6 header destination address
1742 * different from our peer's, do not bother with this.
1743 */
1744 if (!rt || !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr))
1745 return NULL;
1746 return rt6_get_peer_create(rt);
1752} 1747}
1753 1748
1754static void *tcp_v6_tw_get_peer(struct sock *sk) 1749static void *tcp_v6_tw_get_peer(struct sock *sk)