aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-06-10 01:36:36 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-11 05:08:47 -0400
commit97bab73f987e2781129cd6f4b6379bf44d808cc6 (patch)
tree40b10c4c021c8b5524c19f79fcfe4b0799b59952 /net/ipv4
parentc0efc887dcadbdbfe171f028acfab9c7c00e9dde (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.c56
-rw-r--r--net/ipv4/xfrm4_policy.c10
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)
677static inline int rt_valuable(struct rtable *rth) 677static 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
683static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2) 683static 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
1326void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) 1326void 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)
1796static void ipv4_dst_destroy(struct dst_entry *dst) 1802static 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
1823static int ip_rt_bug(struct sk_buff *skb) 1831static int ip_rt_bug(struct sk_buff *skb)
@@ -1919,7 +1927,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
1919static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, 1927static 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}