diff options
author | David S. Miller <davem@davemloft.net> | 2012-06-10 01:36:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-11 05:08:47 -0400 |
commit | 97bab73f987e2781129cd6f4b6379bf44d808cc6 (patch) | |
tree | 40b10c4c021c8b5524c19f79fcfe4b0799b59952 /net/ipv4 | |
parent | c0efc887dcadbdbfe171f028acfab9c7c00e9dde (diff) |
inet: Hide route peer accesses behind helpers.
We encode the pointer(s) into an unsigned long with one state bit.
The state bit is used so we can store the inetpeer tree root to use
when resolving the peer later.
Later the peer roots will be per-FIB table, and this change works to
facilitate that.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/route.c | 56 | ||||
-rw-r--r-- | net/ipv4/xfrm4_policy.c | 10 |
2 files changed, 38 insertions, 28 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2aa663a6ae9e..03e5b614370e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -677,7 +677,7 @@ static inline int rt_fast_clean(struct rtable *rth) | |||
677 | static inline int rt_valuable(struct rtable *rth) | 677 | static inline int rt_valuable(struct rtable *rth) |
678 | { | 678 | { |
679 | return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) || | 679 | return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) || |
680 | (rth->peer && rth->peer->pmtu_expires); | 680 | (rt_has_peer(rth) && rt_peer_ptr(rth)->pmtu_expires); |
681 | } | 681 | } |
682 | 682 | ||
683 | static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2) | 683 | static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2) |
@@ -1325,12 +1325,16 @@ static u32 rt_peer_genid(void) | |||
1325 | 1325 | ||
1326 | void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) | 1326 | void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) |
1327 | { | 1327 | { |
1328 | struct net *net = dev_net(rt->dst.dev); | 1328 | struct inet_peer_base *base; |
1329 | struct inet_peer *peer; | 1329 | struct inet_peer *peer; |
1330 | 1330 | ||
1331 | peer = inet_getpeer_v4(net->ipv4.peers, daddr, create); | 1331 | base = inetpeer_base_ptr(rt->_peer); |
1332 | if (!base) | ||
1333 | return; | ||
1334 | |||
1335 | peer = inet_getpeer_v4(base, daddr, create); | ||
1332 | 1336 | ||
1333 | if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL) | 1337 | if (!rt_set_peer(rt, peer)) |
1334 | inet_putpeer(peer); | 1338 | inet_putpeer(peer); |
1335 | else | 1339 | else |
1336 | rt->rt_peer_genid = rt_peer_genid(); | 1340 | rt->rt_peer_genid = rt_peer_genid(); |
@@ -1533,8 +1537,10 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) | |||
1533 | rt_genid(dev_net(dst->dev))); | 1537 | rt_genid(dev_net(dst->dev))); |
1534 | rt_del(hash, rt); | 1538 | rt_del(hash, rt); |
1535 | ret = NULL; | 1539 | ret = NULL; |
1536 | } else if (rt->peer && peer_pmtu_expired(rt->peer)) { | 1540 | } else if (rt_has_peer(rt)) { |
1537 | dst_metric_set(dst, RTAX_MTU, rt->peer->pmtu_orig); | 1541 | struct inet_peer *peer = rt_peer_ptr(rt); |
1542 | if (peer_pmtu_expired(peer)) | ||
1543 | dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig); | ||
1538 | } | 1544 | } |
1539 | } | 1545 | } |
1540 | return ret; | 1546 | return ret; |
@@ -1796,14 +1802,13 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1796 | static void ipv4_dst_destroy(struct dst_entry *dst) | 1802 | static void ipv4_dst_destroy(struct dst_entry *dst) |
1797 | { | 1803 | { |
1798 | struct rtable *rt = (struct rtable *) dst; | 1804 | struct rtable *rt = (struct rtable *) dst; |
1799 | struct inet_peer *peer = rt->peer; | ||
1800 | 1805 | ||
1801 | if (rt->fi) { | 1806 | if (rt->fi) { |
1802 | fib_info_put(rt->fi); | 1807 | fib_info_put(rt->fi); |
1803 | rt->fi = NULL; | 1808 | rt->fi = NULL; |
1804 | } | 1809 | } |
1805 | if (peer) { | 1810 | if (rt_has_peer(rt)) { |
1806 | rt->peer = NULL; | 1811 | struct inet_peer *peer = rt_peer_ptr(rt); |
1807 | inet_putpeer(peer); | 1812 | inet_putpeer(peer); |
1808 | } | 1813 | } |
1809 | } | 1814 | } |
@@ -1816,8 +1821,11 @@ static void ipv4_link_failure(struct sk_buff *skb) | |||
1816 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); | 1821 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); |
1817 | 1822 | ||
1818 | rt = skb_rtable(skb); | 1823 | rt = skb_rtable(skb); |
1819 | if (rt && rt->peer && peer_pmtu_cleaned(rt->peer)) | 1824 | if (rt && rt_has_peer(rt)) { |
1820 | dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig); | 1825 | struct inet_peer *peer = rt_peer_ptr(rt); |
1826 | if (peer_pmtu_cleaned(peer)) | ||
1827 | dst_metric_set(&rt->dst, RTAX_MTU, peer->pmtu_orig); | ||
1828 | } | ||
1821 | } | 1829 | } |
1822 | 1830 | ||
1823 | static int ip_rt_bug(struct sk_buff *skb) | 1831 | static int ip_rt_bug(struct sk_buff *skb) |
@@ -1919,7 +1927,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) | |||
1919 | static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, | 1927 | static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, |
1920 | struct fib_info *fi) | 1928 | struct fib_info *fi) |
1921 | { | 1929 | { |
1922 | struct net *net = dev_net(rt->dst.dev); | 1930 | struct inet_peer_base *base; |
1923 | struct inet_peer *peer; | 1931 | struct inet_peer *peer; |
1924 | int create = 0; | 1932 | int create = 0; |
1925 | 1933 | ||
@@ -1929,8 +1937,12 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, | |||
1929 | if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) | 1937 | if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) |
1930 | create = 1; | 1938 | create = 1; |
1931 | 1939 | ||
1932 | rt->peer = peer = inet_getpeer_v4(net->ipv4.peers, rt->rt_dst, create); | 1940 | base = inetpeer_base_ptr(rt->_peer); |
1941 | BUG_ON(!base); | ||
1942 | |||
1943 | peer = inet_getpeer_v4(base, rt->rt_dst, create); | ||
1933 | if (peer) { | 1944 | if (peer) { |
1945 | __rt_set_peer(rt, peer); | ||
1934 | rt->rt_peer_genid = rt_peer_genid(); | 1946 | rt->rt_peer_genid = rt_peer_genid(); |
1935 | if (inet_metrics_new(peer)) | 1947 | if (inet_metrics_new(peer)) |
1936 | memcpy(peer->metrics, fi->fib_metrics, | 1948 | memcpy(peer->metrics, fi->fib_metrics, |
@@ -2046,7 +2058,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2046 | rth->rt_gateway = daddr; | 2058 | rth->rt_gateway = daddr; |
2047 | rth->rt_spec_dst= spec_dst; | 2059 | rth->rt_spec_dst= spec_dst; |
2048 | rth->rt_peer_genid = 0; | 2060 | rth->rt_peer_genid = 0; |
2049 | rth->peer = NULL; | 2061 | rt_init_peer(rth, dev_net(dev)->ipv4.peers); |
2050 | rth->fi = NULL; | 2062 | rth->fi = NULL; |
2051 | if (our) { | 2063 | if (our) { |
2052 | rth->dst.input= ip_local_deliver; | 2064 | rth->dst.input= ip_local_deliver; |
@@ -2174,7 +2186,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
2174 | rth->rt_gateway = daddr; | 2186 | rth->rt_gateway = daddr; |
2175 | rth->rt_spec_dst= spec_dst; | 2187 | rth->rt_spec_dst= spec_dst; |
2176 | rth->rt_peer_genid = 0; | 2188 | rth->rt_peer_genid = 0; |
2177 | rth->peer = NULL; | 2189 | rt_init_peer(rth, dev_net(rth->dst.dev)->ipv4.peers); |
2178 | rth->fi = NULL; | 2190 | rth->fi = NULL; |
2179 | 2191 | ||
2180 | rth->dst.input = ip_forward; | 2192 | rth->dst.input = ip_forward; |
@@ -2357,7 +2369,7 @@ local_input: | |||
2357 | rth->rt_gateway = daddr; | 2369 | rth->rt_gateway = daddr; |
2358 | rth->rt_spec_dst= spec_dst; | 2370 | rth->rt_spec_dst= spec_dst; |
2359 | rth->rt_peer_genid = 0; | 2371 | rth->rt_peer_genid = 0; |
2360 | rth->peer = NULL; | 2372 | rt_init_peer(rth, net->ipv4.peers); |
2361 | rth->fi = NULL; | 2373 | rth->fi = NULL; |
2362 | if (res.type == RTN_UNREACHABLE) { | 2374 | if (res.type == RTN_UNREACHABLE) { |
2363 | rth->dst.input= ip_error; | 2375 | rth->dst.input= ip_error; |
@@ -2561,7 +2573,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2561 | rth->rt_gateway = fl4->daddr; | 2573 | rth->rt_gateway = fl4->daddr; |
2562 | rth->rt_spec_dst= fl4->saddr; | 2574 | rth->rt_spec_dst= fl4->saddr; |
2563 | rth->rt_peer_genid = 0; | 2575 | rth->rt_peer_genid = 0; |
2564 | rth->peer = NULL; | 2576 | rt_init_peer(rth, dev_net(dev_out)->ipv4.peers); |
2565 | rth->fi = NULL; | 2577 | rth->fi = NULL; |
2566 | 2578 | ||
2567 | RT_CACHE_STAT_INC(out_slow_tot); | 2579 | RT_CACHE_STAT_INC(out_slow_tot); |
@@ -2898,9 +2910,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2898 | rt->rt_src = ort->rt_src; | 2910 | rt->rt_src = ort->rt_src; |
2899 | rt->rt_gateway = ort->rt_gateway; | 2911 | rt->rt_gateway = ort->rt_gateway; |
2900 | rt->rt_spec_dst = ort->rt_spec_dst; | 2912 | rt->rt_spec_dst = ort->rt_spec_dst; |
2901 | rt->peer = ort->peer; | 2913 | rt_transfer_peer(rt, ort); |
2902 | if (rt->peer) | ||
2903 | atomic_inc(&rt->peer->refcnt); | ||
2904 | rt->fi = ort->fi; | 2914 | rt->fi = ort->fi; |
2905 | if (rt->fi) | 2915 | if (rt->fi) |
2906 | atomic_inc(&rt->fi->fib_clntref); | 2916 | atomic_inc(&rt->fi->fib_clntref); |
@@ -2938,7 +2948,6 @@ static int rt_fill_info(struct net *net, | |||
2938 | struct rtmsg *r; | 2948 | struct rtmsg *r; |
2939 | struct nlmsghdr *nlh; | 2949 | struct nlmsghdr *nlh; |
2940 | unsigned long expires = 0; | 2950 | unsigned long expires = 0; |
2941 | const struct inet_peer *peer = rt->peer; | ||
2942 | u32 id = 0, ts = 0, tsage = 0, error; | 2951 | u32 id = 0, ts = 0, tsage = 0, error; |
2943 | 2952 | ||
2944 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); | 2953 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); |
@@ -2994,8 +3003,9 @@ static int rt_fill_info(struct net *net, | |||
2994 | goto nla_put_failure; | 3003 | goto nla_put_failure; |
2995 | 3004 | ||
2996 | error = rt->dst.error; | 3005 | error = rt->dst.error; |
2997 | if (peer) { | 3006 | if (rt_has_peer(rt)) { |
2998 | inet_peer_refcheck(rt->peer); | 3007 | const struct inet_peer *peer = rt_peer_ptr(rt); |
3008 | inet_peer_refcheck(peer); | ||
2999 | id = atomic_read(&peer->ip_id_count) & 0xffff; | 3009 | id = atomic_read(&peer->ip_id_count) & 0xffff; |
3000 | if (peer->tcp_ts_stamp) { | 3010 | if (peer->tcp_ts_stamp) { |
3001 | ts = peer->tcp_ts; | 3011 | ts = peer->tcp_ts; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 0d3426cb5c4f..8855d8268552 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -90,9 +90,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
90 | xdst->u.dst.dev = dev; | 90 | xdst->u.dst.dev = dev; |
91 | dev_hold(dev); | 91 | dev_hold(dev); |
92 | 92 | ||
93 | xdst->u.rt.peer = rt->peer; | 93 | rt_transfer_peer(&xdst->u.rt, rt); |
94 | if (rt->peer) | ||
95 | atomic_inc(&rt->peer->refcnt); | ||
96 | 94 | ||
97 | /* Sheit... I remember I did this right. Apparently, | 95 | /* Sheit... I remember I did this right. Apparently, |
98 | * it was magically lost, so this code needs audit */ | 96 | * it was magically lost, so this code needs audit */ |
@@ -212,8 +210,10 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) | |||
212 | 210 | ||
213 | dst_destroy_metrics_generic(dst); | 211 | dst_destroy_metrics_generic(dst); |
214 | 212 | ||
215 | if (likely(xdst->u.rt.peer)) | 213 | if (rt_has_peer(&xdst->u.rt)) { |
216 | inet_putpeer(xdst->u.rt.peer); | 214 | struct inet_peer *peer = rt_peer_ptr(&xdst->u.rt); |
215 | inet_putpeer(peer); | ||
216 | } | ||
217 | 217 | ||
218 | xfrm_dst_destroy(xdst); | 218 | xfrm_dst_destroy(xdst); |
219 | } | 219 | } |