aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-12-09 00:16:57 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-09 13:46:36 -0500
commitdefb3519a64141608725e2dac5a5aa9a3c644bae (patch)
tree2f44985e44aef53a0d99991b9f5c2f0eb6dbf4ad /net/ipv6/route.c
parent84b3cdc38cd2882d7ac3c2ae4b6faf5c199874e3 (diff)
net: Abstract away all dst_entry metrics accesses.
Use helper functions to hide all direct accesses, especially writes, to dst_entry metrics values. This will allow us to: 1) More easily change how the metrics are stored. 2) Implement COW for metrics. In particular this will help us put metrics into the inetpeer cache if that is what we end up doing. We can make the _metrics member a pointer instead of an array, initially have it point at the read-only metrics in the FIB, and then on the first set grab an inetpeer entry and point the _metrics member there. Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 026caef0326c..4aed0812b512 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -129,7 +129,6 @@ static struct rt6_info ip6_null_entry_template = {
129 .__use = 1, 129 .__use = 1,
130 .obsolete = -1, 130 .obsolete = -1,
131 .error = -ENETUNREACH, 131 .error = -ENETUNREACH,
132 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
133 .input = ip6_pkt_discard, 132 .input = ip6_pkt_discard,
134 .output = ip6_pkt_discard_out, 133 .output = ip6_pkt_discard_out,
135 }, 134 },
@@ -150,7 +149,6 @@ static struct rt6_info ip6_prohibit_entry_template = {
150 .__use = 1, 149 .__use = 1,
151 .obsolete = -1, 150 .obsolete = -1,
152 .error = -EACCES, 151 .error = -EACCES,
153 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
154 .input = ip6_pkt_prohibit, 152 .input = ip6_pkt_prohibit,
155 .output = ip6_pkt_prohibit_out, 153 .output = ip6_pkt_prohibit_out,
156 }, 154 },
@@ -166,7 +164,6 @@ static struct rt6_info ip6_blk_hole_entry_template = {
166 .__use = 1, 164 .__use = 1,
167 .obsolete = -1, 165 .obsolete = -1,
168 .error = -EINVAL, 166 .error = -EINVAL,
169 .metrics = { [RTAX_HOPLIMIT - 1] = 255, },
170 .input = dst_discard, 167 .input = dst_discard,
171 .output = dst_discard, 168 .output = dst_discard,
172 }, 169 },
@@ -844,7 +841,7 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
844 new->input = dst_discard; 841 new->input = dst_discard;
845 new->output = dst_discard; 842 new->output = dst_discard;
846 843
847 memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); 844 dst_copy_metrics(new, &ort->dst);
848 new->dev = ort->dst.dev; 845 new->dev = ort->dst.dev;
849 if (new->dev) 846 if (new->dev)
850 dev_hold(new->dev); 847 dev_hold(new->dev);
@@ -928,10 +925,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
928 if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) { 925 if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) {
929 rt6->rt6i_flags |= RTF_MODIFIED; 926 rt6->rt6i_flags |= RTF_MODIFIED;
930 if (mtu < IPV6_MIN_MTU) { 927 if (mtu < IPV6_MIN_MTU) {
928 u32 features = dst_metric(dst, RTAX_FEATURES);
931 mtu = IPV6_MIN_MTU; 929 mtu = IPV6_MIN_MTU;
932 dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; 930 features |= RTAX_FEATURE_ALLFRAG;
931 dst_metric_set(dst, RTAX_FEATURES, features);
933 } 932 }
934 dst->metrics[RTAX_MTU-1] = mtu; 933 dst_metric_set(dst, RTAX_MTU, mtu);
935 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); 934 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
936 } 935 }
937} 936}
@@ -989,9 +988,9 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
989 rt->rt6i_idev = idev; 988 rt->rt6i_idev = idev;
990 rt->rt6i_nexthop = neigh; 989 rt->rt6i_nexthop = neigh;
991 atomic_set(&rt->dst.__refcnt, 1); 990 atomic_set(&rt->dst.__refcnt, 1);
992 rt->dst.metrics[RTAX_HOPLIMIT-1] = 255; 991 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
993 rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); 992 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
994 rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); 993 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
995 rt->dst.output = ip6_output; 994 rt->dst.output = ip6_output;
996 995
997#if 0 /* there's no chance to use these for ndisc */ 996#if 0 /* there's no chance to use these for ndisc */
@@ -1305,17 +1304,17 @@ install_route:
1305 goto out; 1304 goto out;
1306 } 1305 }
1307 1306
1308 rt->dst.metrics[type - 1] = nla_get_u32(nla); 1307 dst_metric_set(&rt->dst, type, nla_get_u32(nla));
1309 } 1308 }
1310 } 1309 }
1311 } 1310 }
1312 1311
1313 if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) 1312 if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0)
1314 rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; 1313 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
1315 if (!dst_mtu(&rt->dst)) 1314 if (!dst_mtu(&rt->dst))
1316 rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); 1315 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev));
1317 if (!dst_metric(&rt->dst, RTAX_ADVMSS)) 1316 if (!dst_metric(&rt->dst, RTAX_ADVMSS))
1318 rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); 1317 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
1319 rt->dst.dev = dev; 1318 rt->dst.dev = dev;
1320 rt->rt6i_idev = idev; 1319 rt->rt6i_idev = idev;
1321 rt->rt6i_table = table; 1320 rt->rt6i_table = table;
@@ -1541,9 +1540,9 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1541 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); 1540 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
1542 nrt->rt6i_nexthop = neigh_clone(neigh); 1541 nrt->rt6i_nexthop = neigh_clone(neigh);
1543 /* Reset pmtu, it may be better */ 1542 /* Reset pmtu, it may be better */
1544 nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); 1543 dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev));
1545 nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), 1544 dst_metric_set(&nrt->dst, RTAX_ADVMSS, ipv6_advmss(dev_net(neigh->dev),
1546 dst_mtu(&nrt->dst)); 1545 dst_mtu(&nrt->dst)));
1547 1546
1548 if (ip6_ins_rt(nrt)) 1547 if (ip6_ins_rt(nrt))
1549 goto out; 1548 goto out;
@@ -1602,9 +1601,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
1602 would return automatically. 1601 would return automatically.
1603 */ 1602 */
1604 if (rt->rt6i_flags & RTF_CACHE) { 1603 if (rt->rt6i_flags & RTF_CACHE) {
1605 rt->dst.metrics[RTAX_MTU-1] = pmtu; 1604 dst_metric_set(&rt->dst, RTAX_MTU, pmtu);
1606 if (allfrag) 1605 if (allfrag) {
1607 rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; 1606 u32 features = dst_metric(&rt->dst, RTAX_FEATURES);
1607 features |= RTAX_FEATURE_ALLFRAG;
1608 dst_metric_set(&rt->dst, RTAX_FEATURES, features);
1609 }
1608 dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); 1610 dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
1609 rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; 1611 rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
1610 goto out; 1612 goto out;
@@ -1621,9 +1623,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
1621 nrt = rt6_alloc_clone(rt, daddr); 1623 nrt = rt6_alloc_clone(rt, daddr);
1622 1624
1623 if (nrt) { 1625 if (nrt) {
1624 nrt->dst.metrics[RTAX_MTU-1] = pmtu; 1626 dst_metric_set(&nrt->dst, RTAX_MTU, pmtu);
1625 if (allfrag) 1627 if (allfrag) {
1626 nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; 1628 u32 features = dst_metric(&nrt->dst, RTAX_FEATURES);
1629 features |= RTAX_FEATURE_ALLFRAG;
1630 dst_metric_set(&nrt->dst, RTAX_FEATURES, features);
1631 }
1627 1632
1628 /* According to RFC 1981, detecting PMTU increase shouldn't be 1633 /* According to RFC 1981, detecting PMTU increase shouldn't be
1629 * happened within 5 mins, the recommended timer is 10 mins. 1634 * happened within 5 mins, the recommended timer is 10 mins.
@@ -1674,7 +1679,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1674 rt->dst.input = ort->dst.input; 1679 rt->dst.input = ort->dst.input;
1675 rt->dst.output = ort->dst.output; 1680 rt->dst.output = ort->dst.output;
1676 1681
1677 memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); 1682 dst_copy_metrics(&rt->dst, &ort->dst);
1678 rt->dst.error = ort->dst.error; 1683 rt->dst.error = ort->dst.error;
1679 rt->dst.dev = ort->dst.dev; 1684 rt->dst.dev = ort->dst.dev;
1680 if (rt->dst.dev) 1685 if (rt->dst.dev)
@@ -1966,9 +1971,9 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1966 rt->dst.output = ip6_output; 1971 rt->dst.output = ip6_output;
1967 rt->rt6i_dev = net->loopback_dev; 1972 rt->rt6i_dev = net->loopback_dev;
1968 rt->rt6i_idev = idev; 1973 rt->rt6i_idev = idev;
1969 rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); 1974 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
1970 rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); 1975 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
1971 rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; 1976 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
1972 rt->dst.obsolete = -1; 1977 rt->dst.obsolete = -1;
1973 1978
1974 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; 1979 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
@@ -2068,8 +2073,8 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
2068 (dst_mtu(&rt->dst) >= arg->mtu || 2073 (dst_mtu(&rt->dst) >= arg->mtu ||
2069 (dst_mtu(&rt->dst) < arg->mtu && 2074 (dst_mtu(&rt->dst) < arg->mtu &&
2070 dst_mtu(&rt->dst) == idev->cnf.mtu6))) { 2075 dst_mtu(&rt->dst) == idev->cnf.mtu6))) {
2071 rt->dst.metrics[RTAX_MTU-1] = arg->mtu; 2076 dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu);
2072 rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); 2077 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, arg->mtu));
2073 } 2078 }
2074 return 0; 2079 return 0;
2075} 2080}
@@ -2295,7 +2300,7 @@ static int rt6_fill_node(struct net *net,
2295 NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); 2300 NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
2296 } 2301 }
2297 2302
2298 if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) 2303 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2299 goto nla_put_failure; 2304 goto nla_put_failure;
2300 2305
2301 if (rt->dst.neighbour) 2306 if (rt->dst.neighbour)
@@ -2686,6 +2691,7 @@ static int __net_init ip6_route_net_init(struct net *net)
2686 net->ipv6.ip6_null_entry->dst.path = 2691 net->ipv6.ip6_null_entry->dst.path =
2687 (struct dst_entry *)net->ipv6.ip6_null_entry; 2692 (struct dst_entry *)net->ipv6.ip6_null_entry;
2688 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2693 net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2694 dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255);
2689 2695
2690#ifdef CONFIG_IPV6_MULTIPLE_TABLES 2696#ifdef CONFIG_IPV6_MULTIPLE_TABLES
2691 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, 2697 net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2696,6 +2702,7 @@ static int __net_init ip6_route_net_init(struct net *net)
2696 net->ipv6.ip6_prohibit_entry->dst.path = 2702 net->ipv6.ip6_prohibit_entry->dst.path =
2697 (struct dst_entry *)net->ipv6.ip6_prohibit_entry; 2703 (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
2698 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2704 net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2705 dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255);
2699 2706
2700 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, 2707 net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
2701 sizeof(*net->ipv6.ip6_blk_hole_entry), 2708 sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2705,6 +2712,7 @@ static int __net_init ip6_route_net_init(struct net *net)
2705 net->ipv6.ip6_blk_hole_entry->dst.path = 2712 net->ipv6.ip6_blk_hole_entry->dst.path =
2706 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; 2713 (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
2707 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; 2714 net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
2715 dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255);
2708#endif 2716#endif
2709 2717
2710 net->ipv6.sysctl.flush_delay = 0; 2718 net->ipv6.sysctl.flush_delay = 0;