aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
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/ipv6
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/ipv6')
-rw-r--r--net/ipv6/route.c42
-rw-r--r--net/ipv6/xfrm6_policy.c10
2 files changed, 29 insertions, 23 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8fc41d502bbd..17a9b8687f29 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -258,16 +258,18 @@ static struct rt6_info ip6_blk_hole_entry_template = {
258#endif 258#endif
259 259
260/* allocate dst with ip6_dst_ops */ 260/* allocate dst with ip6_dst_ops */
261static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, 261static inline struct rt6_info *ip6_dst_alloc(struct net *net,
262 struct net_device *dev, 262 struct net_device *dev,
263 int flags) 263 int flags)
264{ 264{
265 struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); 265 struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
266 0, 0, flags);
266 267
267 if (rt) 268 if (rt) {
268 memset(&rt->rt6i_table, 0, 269 memset(&rt->rt6i_table, 0,
269 sizeof(*rt) - sizeof(struct dst_entry)); 270 sizeof(*rt) - sizeof(struct dst_entry));
270 271 rt6_init_peer(rt, net->ipv6.peers);
272 }
271 return rt; 273 return rt;
272} 274}
273 275
@@ -275,7 +277,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
275{ 277{
276 struct rt6_info *rt = (struct rt6_info *)dst; 278 struct rt6_info *rt = (struct rt6_info *)dst;
277 struct inet6_dev *idev = rt->rt6i_idev; 279 struct inet6_dev *idev = rt->rt6i_idev;
278 struct inet_peer *peer = rt->rt6i_peer;
279 280
280 if (!(rt->dst.flags & DST_HOST)) 281 if (!(rt->dst.flags & DST_HOST))
281 dst_destroy_metrics_generic(dst); 282 dst_destroy_metrics_generic(dst);
@@ -288,8 +289,8 @@ static void ip6_dst_destroy(struct dst_entry *dst)
288 if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) 289 if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from)
289 dst_release(dst->from); 290 dst_release(dst->from);
290 291
291 if (peer) { 292 if (rt6_has_peer(rt)) {
292 rt->rt6i_peer = NULL; 293 struct inet_peer *peer = rt6_peer_ptr(rt);
293 inet_putpeer(peer); 294 inet_putpeer(peer);
294 } 295 }
295} 296}
@@ -303,11 +304,15 @@ static u32 rt6_peer_genid(void)
303 304
304void rt6_bind_peer(struct rt6_info *rt, int create) 305void rt6_bind_peer(struct rt6_info *rt, int create)
305{ 306{
306 struct net *net = dev_net(rt->dst.dev); 307 struct inet_peer_base *base;
307 struct inet_peer *peer; 308 struct inet_peer *peer;
308 309
309 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, create); 310 base = inetpeer_base_ptr(rt->_rt6i_peer);
310 if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) 311 if (!base)
312 return;
313
314 peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
315 if (!rt6_set_peer(rt, peer))
311 inet_putpeer(peer); 316 inet_putpeer(peer);
312 else 317 else
313 rt->rt6i_peer_genid = rt6_peer_genid(); 318 rt->rt6i_peer_genid = rt6_peer_genid();
@@ -950,6 +955,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
950 rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0); 955 rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0);
951 if (rt) { 956 if (rt) {
952 memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); 957 memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry));
958 rt6_init_peer(rt, net->ipv6.peers);
953 959
954 new = &rt->dst; 960 new = &rt->dst;
955 961
@@ -994,7 +1000,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
994 1000
995 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { 1001 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
996 if (rt->rt6i_peer_genid != rt6_peer_genid()) { 1002 if (rt->rt6i_peer_genid != rt6_peer_genid()) {
997 if (!rt->rt6i_peer) 1003 if (!rt6_has_peer(rt))
998 rt6_bind_peer(rt, 0); 1004 rt6_bind_peer(rt, 0);
999 rt->rt6i_peer_genid = rt6_peer_genid(); 1005 rt->rt6i_peer_genid = rt6_peer_genid();
1000 } 1006 }
@@ -1108,7 +1114,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1108 if (unlikely(!idev)) 1114 if (unlikely(!idev))
1109 return ERR_PTR(-ENODEV); 1115 return ERR_PTR(-ENODEV);
1110 1116
1111 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); 1117 rt = ip6_dst_alloc(net, dev, 0);
1112 if (unlikely(!rt)) { 1118 if (unlikely(!rt)) {
1113 in6_dev_put(idev); 1119 in6_dev_put(idev);
1114 dst = ERR_PTR(-ENOMEM); 1120 dst = ERR_PTR(-ENOMEM);
@@ -1290,7 +1296,7 @@ int ip6_route_add(struct fib6_config *cfg)
1290 if (!table) 1296 if (!table)
1291 goto out; 1297 goto out;
1292 1298
1293 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT); 1299 rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT);
1294 1300
1295 if (!rt) { 1301 if (!rt) {
1296 err = -ENOMEM; 1302 err = -ENOMEM;
@@ -1812,8 +1818,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
1812 const struct in6_addr *dest) 1818 const struct in6_addr *dest)
1813{ 1819{
1814 struct net *net = dev_net(ort->dst.dev); 1820 struct net *net = dev_net(ort->dst.dev);
1815 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, 1821 struct rt6_info *rt = ip6_dst_alloc(net, ort->dst.dev, 0);
1816 ort->dst.dev, 0);
1817 1822
1818 if (rt) { 1823 if (rt) {
1819 rt->dst.input = ort->dst.input; 1824 rt->dst.input = ort->dst.input;
@@ -2097,8 +2102,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2097 bool anycast) 2102 bool anycast)
2098{ 2103{
2099 struct net *net = dev_net(idev->dev); 2104 struct net *net = dev_net(idev->dev);
2100 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, 2105 struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0);
2101 net->loopback_dev, 0);
2102 int err; 2106 int err;
2103 2107
2104 if (!rt) { 2108 if (!rt) {
@@ -2519,7 +2523,9 @@ static int rt6_fill_node(struct net *net,
2519 else 2523 else
2520 expires = INT_MAX; 2524 expires = INT_MAX;
2521 2525
2522 peer = rt->rt6i_peer; 2526 peer = NULL;
2527 if (rt6_has_peer(rt))
2528 peer = rt6_peer_ptr(rt);
2523 ts = tsage = 0; 2529 ts = tsage = 0;
2524 if (peer && peer->tcp_ts_stamp) { 2530 if (peer && peer->tcp_ts_stamp) {
2525 ts = peer->tcp_ts; 2531 ts = peer->tcp_ts;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8625fba96db9..d7494845efbf 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -99,9 +99,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
99 if (!xdst->u.rt6.rt6i_idev) 99 if (!xdst->u.rt6.rt6i_idev)
100 return -ENODEV; 100 return -ENODEV;
101 101
102 xdst->u.rt6.rt6i_peer = rt->rt6i_peer; 102 rt6_transfer_peer(&xdst->u.rt6, rt);
103 if (rt->rt6i_peer)
104 atomic_inc(&rt->rt6i_peer->refcnt);
105 103
106 /* Sheit... I remember I did this right. Apparently, 104 /* Sheit... I remember I did this right. Apparently,
107 * it was magically lost, so this code needs audit */ 105 * it was magically lost, so this code needs audit */
@@ -223,8 +221,10 @@ static void xfrm6_dst_destroy(struct dst_entry *dst)
223 if (likely(xdst->u.rt6.rt6i_idev)) 221 if (likely(xdst->u.rt6.rt6i_idev))
224 in6_dev_put(xdst->u.rt6.rt6i_idev); 222 in6_dev_put(xdst->u.rt6.rt6i_idev);
225 dst_destroy_metrics_generic(dst); 223 dst_destroy_metrics_generic(dst);
226 if (likely(xdst->u.rt6.rt6i_peer)) 224 if (rt6_has_peer(&xdst->u.rt6)) {
227 inet_putpeer(xdst->u.rt6.rt6i_peer); 225 struct inet_peer *peer = rt6_peer_ptr(&xdst->u.rt6);
226 inet_putpeer(peer);
227 }
228 xfrm_dst_destroy(xdst); 228 xfrm_dst_destroy(xdst);
229} 229}
230 230