diff options
author | David S. Miller <davem@davemloft.net> | 2010-12-14 16:01:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-14 16:01:14 -0500 |
commit | d33e455337ea2c71d09d7f4367d6ad6dd32b6965 (patch) | |
tree | d1b35b1be5ab73df6f7e57b86a2e68fad2990adf /net | |
parent | 9fe146aef44afe5ec677d8150b6ae94e09b773f7 (diff) |
net: Abstract default MTU metric calculation behind an accessor.
Like RTAX_ADVMSS, make the default calculation go through a dst_ops
method rather than caching the computation in the routing cache
entries.
Now dst metrics are pretty much left as-is when new entries are
created, thus optimizing metric sharing becomes a real possibility.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/decnet/dn_route.c | 10 | ||||
-rw-r--r-- | net/ipv4/route.c | 29 | ||||
-rw-r--r-- | net/ipv6/route.c | 37 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 7 |
4 files changed, 51 insertions, 32 deletions
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index b8a5c0515be8..5e636365d33c 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -111,6 +111,7 @@ static unsigned long dn_rt_deadline; | |||
111 | static int dn_dst_gc(struct dst_ops *ops); | 111 | static int dn_dst_gc(struct dst_ops *ops); |
112 | static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); | 112 | static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); |
113 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); | 113 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); |
114 | static unsigned int dn_dst_default_mtu(const struct dst_entry *dst); | ||
114 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); | 115 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); |
115 | static void dn_dst_link_failure(struct sk_buff *); | 116 | static void dn_dst_link_failure(struct sk_buff *); |
116 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); | 117 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); |
@@ -131,6 +132,7 @@ static struct dst_ops dn_dst_ops = { | |||
131 | .gc = dn_dst_gc, | 132 | .gc = dn_dst_gc, |
132 | .check = dn_dst_check, | 133 | .check = dn_dst_check, |
133 | .default_advmss = dn_dst_default_advmss, | 134 | .default_advmss = dn_dst_default_advmss, |
135 | .default_mtu = dn_dst_default_mtu, | ||
134 | .negative_advice = dn_dst_negative_advice, | 136 | .negative_advice = dn_dst_negative_advice, |
135 | .link_failure = dn_dst_link_failure, | 137 | .link_failure = dn_dst_link_failure, |
136 | .update_pmtu = dn_dst_update_pmtu, | 138 | .update_pmtu = dn_dst_update_pmtu, |
@@ -803,6 +805,11 @@ static unsigned int dn_dst_default_advmss(const struct dst_entry *dst) | |||
803 | return dn_mss_from_pmtu(dst->dev, dst_mtu(dst)); | 805 | return dn_mss_from_pmtu(dst->dev, dst_mtu(dst)); |
804 | } | 806 | } |
805 | 807 | ||
808 | static unsigned int dn_dst_default_mtu(const struct dst_entry *dst) | ||
809 | { | ||
810 | return dst->dev->mtu; | ||
811 | } | ||
812 | |||
806 | static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | 813 | static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) |
807 | { | 814 | { |
808 | struct dn_fib_info *fi = res->fi; | 815 | struct dn_fib_info *fi = res->fi; |
@@ -825,8 +832,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | |||
825 | rt->dst.neighbour = n; | 832 | rt->dst.neighbour = n; |
826 | } | 833 | } |
827 | 834 | ||
828 | if (dst_metric(&rt->dst, RTAX_MTU) == 0 || | 835 | if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) |
829 | dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) | ||
830 | dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu); | 836 | dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu); |
831 | metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS); | 837 | metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS); |
832 | if (metric) { | 838 | if (metric) { |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 80997333db0c..ae520963540f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -140,6 +140,7 @@ static unsigned long expires_ljiffies; | |||
140 | 140 | ||
141 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); | 141 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); |
142 | static unsigned int ipv4_default_advmss(const struct dst_entry *dst); | 142 | static unsigned int ipv4_default_advmss(const struct dst_entry *dst); |
143 | static unsigned int ipv4_default_mtu(const struct dst_entry *dst); | ||
143 | static void ipv4_dst_destroy(struct dst_entry *dst); | 144 | static void ipv4_dst_destroy(struct dst_entry *dst); |
144 | static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); | 145 | static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); |
145 | static void ipv4_link_failure(struct sk_buff *skb); | 146 | static void ipv4_link_failure(struct sk_buff *skb); |
@@ -157,6 +158,7 @@ static struct dst_ops ipv4_dst_ops = { | |||
157 | .gc = rt_garbage_collect, | 158 | .gc = rt_garbage_collect, |
158 | .check = ipv4_dst_check, | 159 | .check = ipv4_dst_check, |
159 | .default_advmss = ipv4_default_advmss, | 160 | .default_advmss = ipv4_default_advmss, |
161 | .default_mtu = ipv4_default_mtu, | ||
160 | .destroy = ipv4_dst_destroy, | 162 | .destroy = ipv4_dst_destroy, |
161 | .ifdown = ipv4_dst_ifdown, | 163 | .ifdown = ipv4_dst_ifdown, |
162 | .negative_advice = ipv4_negative_advice, | 164 | .negative_advice = ipv4_negative_advice, |
@@ -1812,6 +1814,23 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst) | |||
1812 | return advmss; | 1814 | return advmss; |
1813 | } | 1815 | } |
1814 | 1816 | ||
1817 | static unsigned int ipv4_default_mtu(const struct dst_entry *dst) | ||
1818 | { | ||
1819 | unsigned int mtu = dst->dev->mtu; | ||
1820 | |||
1821 | if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { | ||
1822 | const struct rtable *rt = (const struct rtable *) dst; | ||
1823 | |||
1824 | if (rt->rt_gateway != rt->rt_dst && mtu > 576) | ||
1825 | mtu = 576; | ||
1826 | } | ||
1827 | |||
1828 | if (mtu > IP_MAX_MTU) | ||
1829 | mtu = IP_MAX_MTU; | ||
1830 | |||
1831 | return mtu; | ||
1832 | } | ||
1833 | |||
1815 | static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) | 1834 | static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) |
1816 | { | 1835 | { |
1817 | struct dst_entry *dst = &rt->dst; | 1836 | struct dst_entry *dst = &rt->dst; |
@@ -1822,18 +1841,10 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) | |||
1822 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 1841 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
1823 | rt->rt_gateway = FIB_RES_GW(*res); | 1842 | rt->rt_gateway = FIB_RES_GW(*res); |
1824 | dst_import_metrics(dst, fi->fib_metrics); | 1843 | dst_import_metrics(dst, fi->fib_metrics); |
1825 | if (fi->fib_mtu == 0) { | ||
1826 | dst_metric_set(dst, RTAX_MTU, dst->dev->mtu); | ||
1827 | if (dst_metric_locked(dst, RTAX_MTU) && | ||
1828 | rt->rt_gateway != rt->rt_dst && | ||
1829 | dst->dev->mtu > 576) | ||
1830 | dst_metric_set(dst, RTAX_MTU, 576); | ||
1831 | } | ||
1832 | #ifdef CONFIG_NET_CLS_ROUTE | 1844 | #ifdef CONFIG_NET_CLS_ROUTE |
1833 | dst->tclassid = FIB_RES_NH(*res).nh_tclassid; | 1845 | dst->tclassid = FIB_RES_NH(*res).nh_tclassid; |
1834 | #endif | 1846 | #endif |
1835 | } else | 1847 | } |
1836 | dst_metric_set(dst, RTAX_MTU, dst->dev->mtu); | ||
1837 | 1848 | ||
1838 | if (dst_mtu(dst) > IP_MAX_MTU) | 1849 | if (dst_mtu(dst) > IP_MAX_MTU) |
1839 | dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU); | 1850 | dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d9cb832be529..e7efb269a6e9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -77,6 +77,7 @@ | |||
77 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); | 77 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); |
78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
79 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 79 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
80 | static unsigned int ip6_default_mtu(const struct dst_entry *dst); | ||
80 | static struct dst_entry *ip6_negative_advice(struct dst_entry *); | 81 | static struct dst_entry *ip6_negative_advice(struct dst_entry *); |
81 | static void ip6_dst_destroy(struct dst_entry *); | 82 | static void ip6_dst_destroy(struct dst_entry *); |
82 | static void ip6_dst_ifdown(struct dst_entry *, | 83 | static void ip6_dst_ifdown(struct dst_entry *, |
@@ -105,6 +106,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
105 | .gc_thresh = 1024, | 106 | .gc_thresh = 1024, |
106 | .check = ip6_dst_check, | 107 | .check = ip6_dst_check, |
107 | .default_advmss = ip6_default_advmss, | 108 | .default_advmss = ip6_default_advmss, |
109 | .default_mtu = ip6_default_mtu, | ||
108 | .destroy = ip6_dst_destroy, | 110 | .destroy = ip6_dst_destroy, |
109 | .ifdown = ip6_dst_ifdown, | 111 | .ifdown = ip6_dst_ifdown, |
110 | .negative_advice = ip6_negative_advice, | 112 | .negative_advice = ip6_negative_advice, |
@@ -937,8 +939,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
937 | } | 939 | } |
938 | } | 940 | } |
939 | 941 | ||
940 | static int ipv6_get_mtu(struct net_device *dev); | ||
941 | |||
942 | static unsigned int ip6_default_advmss(const struct dst_entry *dst) | 942 | static unsigned int ip6_default_advmss(const struct dst_entry *dst) |
943 | { | 943 | { |
944 | struct net_device *dev = dst->dev; | 944 | struct net_device *dev = dst->dev; |
@@ -961,6 +961,20 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst) | |||
961 | return mtu; | 961 | return mtu; |
962 | } | 962 | } |
963 | 963 | ||
964 | static unsigned int ip6_default_mtu(const struct dst_entry *dst) | ||
965 | { | ||
966 | unsigned int mtu = IPV6_MIN_MTU; | ||
967 | struct inet6_dev *idev; | ||
968 | |||
969 | rcu_read_lock(); | ||
970 | idev = __in6_dev_get(dst->dev); | ||
971 | if (idev) | ||
972 | mtu = idev->cnf.mtu6; | ||
973 | rcu_read_unlock(); | ||
974 | |||
975 | return mtu; | ||
976 | } | ||
977 | |||
964 | static struct dst_entry *icmp6_dst_gc_list; | 978 | static struct dst_entry *icmp6_dst_gc_list; |
965 | static DEFINE_SPINLOCK(icmp6_dst_lock); | 979 | static DEFINE_SPINLOCK(icmp6_dst_lock); |
966 | 980 | ||
@@ -995,7 +1009,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
995 | rt->rt6i_nexthop = neigh; | 1009 | rt->rt6i_nexthop = neigh; |
996 | atomic_set(&rt->dst.__refcnt, 1); | 1010 | atomic_set(&rt->dst.__refcnt, 1); |
997 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1011 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
998 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); | ||
999 | rt->dst.output = ip6_output; | 1012 | rt->dst.output = ip6_output; |
1000 | 1013 | ||
1001 | #if 0 /* there's no chance to use these for ndisc */ | 1014 | #if 0 /* there's no chance to use these for ndisc */ |
@@ -1094,19 +1107,6 @@ out: | |||
1094 | Remove it only when all the things will work! | 1107 | Remove it only when all the things will work! |
1095 | */ | 1108 | */ |
1096 | 1109 | ||
1097 | static int ipv6_get_mtu(struct net_device *dev) | ||
1098 | { | ||
1099 | int mtu = IPV6_MIN_MTU; | ||
1100 | struct inet6_dev *idev; | ||
1101 | |||
1102 | rcu_read_lock(); | ||
1103 | idev = __in6_dev_get(dev); | ||
1104 | if (idev) | ||
1105 | mtu = idev->cnf.mtu6; | ||
1106 | rcu_read_unlock(); | ||
1107 | return mtu; | ||
1108 | } | ||
1109 | |||
1110 | int ip6_dst_hoplimit(struct dst_entry *dst) | 1110 | int ip6_dst_hoplimit(struct dst_entry *dst) |
1111 | { | 1111 | { |
1112 | int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); | 1112 | int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); |
@@ -1315,8 +1315,6 @@ install_route: | |||
1315 | } | 1315 | } |
1316 | } | 1316 | } |
1317 | 1317 | ||
1318 | if (!dst_mtu(&rt->dst)) | ||
1319 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev)); | ||
1320 | rt->dst.dev = dev; | 1318 | rt->dst.dev = dev; |
1321 | rt->rt6i_idev = idev; | 1319 | rt->rt6i_idev = idev; |
1322 | rt->rt6i_table = table; | 1320 | rt->rt6i_table = table; |
@@ -1541,8 +1539,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1541 | 1539 | ||
1542 | 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); |
1543 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1541 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1544 | /* Reset pmtu, it may be better */ | ||
1545 | dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev)); | ||
1546 | 1542 | ||
1547 | if (ip6_ins_rt(nrt)) | 1543 | if (ip6_ins_rt(nrt)) |
1548 | goto out; | 1544 | goto out; |
@@ -1971,7 +1967,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1971 | rt->dst.output = ip6_output; | 1967 | rt->dst.output = ip6_output; |
1972 | rt->rt6i_dev = net->loopback_dev; | 1968 | rt->rt6i_dev = net->loopback_dev; |
1973 | rt->rt6i_idev = idev; | 1969 | rt->rt6i_idev = idev; |
1974 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); | ||
1975 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); | 1970 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); |
1976 | rt->dst.obsolete = -1; | 1971 | rt->dst.obsolete = -1; |
1977 | 1972 | ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 36936c8ae961..8b3ef404c794 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2366,6 +2366,11 @@ static unsigned int xfrm_default_advmss(const struct dst_entry *dst) | |||
2366 | return dst_metric_advmss(dst->path); | 2366 | return dst_metric_advmss(dst->path); |
2367 | } | 2367 | } |
2368 | 2368 | ||
2369 | static unsigned int xfrm_default_mtu(const struct dst_entry *dst) | ||
2370 | { | ||
2371 | return dst_mtu(dst->path); | ||
2372 | } | ||
2373 | |||
2369 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2374 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |
2370 | { | 2375 | { |
2371 | struct net *net; | 2376 | struct net *net; |
@@ -2385,6 +2390,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2385 | dst_ops->check = xfrm_dst_check; | 2390 | dst_ops->check = xfrm_dst_check; |
2386 | if (likely(dst_ops->default_advmss == NULL)) | 2391 | if (likely(dst_ops->default_advmss == NULL)) |
2387 | dst_ops->default_advmss = xfrm_default_advmss; | 2392 | dst_ops->default_advmss = xfrm_default_advmss; |
2393 | if (likely(dst_ops->default_mtu == NULL)) | ||
2394 | dst_ops->default_mtu = xfrm_default_mtu; | ||
2388 | if (likely(dst_ops->negative_advice == NULL)) | 2395 | if (likely(dst_ops->negative_advice == NULL)) |
2389 | dst_ops->negative_advice = xfrm_negative_advice; | 2396 | dst_ops->negative_advice = xfrm_negative_advice; |
2390 | if (likely(dst_ops->link_failure == NULL)) | 2397 | if (likely(dst_ops->link_failure == NULL)) |