aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-12-13 15:52:14 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-13 15:52:14 -0500
commit0dbaee3b37e118a96bb7b8eb0d9bbaeeb46264be (patch)
tree37000c5d7e663e4ae9800a7bcde9934984b8bae9 /net/ipv6
parentcc6f02dd490dac4ad821d5077b934c9b37037cd0 (diff)
net: Abstract default ADVMSS behind an accessor.
Make all RTAX_ADVMSS metric accesses go through a new helper function, dst_metric_advmss(). Leave the actual default metric as "zero" in the real metric slot, and compute the actual default value dynamically via a new dst_ops AF specific callback. For stacked IPSEC routes, we use the advmss of the path which preserves existing behavior. Unlike ipv4/ipv6, DecNET ties the advmss to the mtu and thus updates advmss on pmtu updates. This inconsistency in advmss handling results in more raw metric accesses than I wish we ended up with. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/route.c16
-rw-r--r--net/ipv6/tcp_ipv6.c2
2 files changed, 8 insertions, 10 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 98796b0dc2b7..d9cb832be529 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -76,6 +76,7 @@
76 76
77static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); 77static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
78static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); 78static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
79static unsigned int ip6_default_advmss(const struct dst_entry *dst);
79static struct dst_entry *ip6_negative_advice(struct dst_entry *); 80static struct dst_entry *ip6_negative_advice(struct dst_entry *);
80static void ip6_dst_destroy(struct dst_entry *); 81static void ip6_dst_destroy(struct dst_entry *);
81static void ip6_dst_ifdown(struct dst_entry *, 82static void ip6_dst_ifdown(struct dst_entry *,
@@ -103,6 +104,7 @@ static struct dst_ops ip6_dst_ops_template = {
103 .gc = ip6_dst_gc, 104 .gc = ip6_dst_gc,
104 .gc_thresh = 1024, 105 .gc_thresh = 1024,
105 .check = ip6_dst_check, 106 .check = ip6_dst_check,
107 .default_advmss = ip6_default_advmss,
106 .destroy = ip6_dst_destroy, 108 .destroy = ip6_dst_destroy,
107 .ifdown = ip6_dst_ifdown, 109 .ifdown = ip6_dst_ifdown,
108 .negative_advice = ip6_negative_advice, 110 .negative_advice = ip6_negative_advice,
@@ -937,8 +939,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
937 939
938static int ipv6_get_mtu(struct net_device *dev); 940static int ipv6_get_mtu(struct net_device *dev);
939 941
940static inline unsigned int ipv6_advmss(struct net *net, unsigned int mtu) 942static unsigned int ip6_default_advmss(const struct dst_entry *dst)
941{ 943{
944 struct net_device *dev = dst->dev;
945 unsigned int mtu = dst_mtu(dst);
946 struct net *net = dev_net(dev);
947
942 mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); 948 mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
943 949
944 if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) 950 if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
@@ -990,7 +996,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
990 atomic_set(&rt->dst.__refcnt, 1); 996 atomic_set(&rt->dst.__refcnt, 1);
991 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); 997 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
992 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); 998 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
993 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
994 rt->dst.output = ip6_output; 999 rt->dst.output = ip6_output;
995 1000
996#if 0 /* there's no chance to use these for ndisc */ 1001#if 0 /* there's no chance to use these for ndisc */
@@ -1312,8 +1317,6 @@ install_route:
1312 1317
1313 if (!dst_mtu(&rt->dst)) 1318 if (!dst_mtu(&rt->dst))
1314 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev)); 1319 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev));
1315 if (!dst_metric(&rt->dst, RTAX_ADVMSS))
1316 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
1317 rt->dst.dev = dev; 1320 rt->dst.dev = dev;
1318 rt->rt6i_idev = idev; 1321 rt->rt6i_idev = idev;
1319 rt->rt6i_table = table; 1322 rt->rt6i_table = table;
@@ -1540,8 +1543,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
1540 nrt->rt6i_nexthop = neigh_clone(neigh); 1543 nrt->rt6i_nexthop = neigh_clone(neigh);
1541 /* Reset pmtu, it may be better */ 1544 /* Reset pmtu, it may be better */
1542 dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev)); 1545 dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev));
1543 dst_metric_set(&nrt->dst, RTAX_ADVMSS, ipv6_advmss(dev_net(neigh->dev),
1544 dst_mtu(&nrt->dst)));
1545 1546
1546 if (ip6_ins_rt(nrt)) 1547 if (ip6_ins_rt(nrt))
1547 goto out; 1548 goto out;
@@ -1971,7 +1972,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1971 rt->rt6i_dev = net->loopback_dev; 1972 rt->rt6i_dev = net->loopback_dev;
1972 rt->rt6i_idev = idev; 1973 rt->rt6i_idev = idev;
1973 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); 1974 dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev));
1974 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst)));
1975 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); 1975 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
1976 rt->dst.obsolete = -1; 1976 rt->dst.obsolete = -1;
1977 1977
@@ -2041,7 +2041,6 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
2041{ 2041{
2042 struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg; 2042 struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
2043 struct inet6_dev *idev; 2043 struct inet6_dev *idev;
2044 struct net *net = dev_net(arg->dev);
2045 2044
2046 /* In IPv6 pmtu discovery is not optional, 2045 /* In IPv6 pmtu discovery is not optional,
2047 so that RTAX_MTU lock cannot disable it. 2046 so that RTAX_MTU lock cannot disable it.
@@ -2073,7 +2072,6 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
2073 (dst_mtu(&rt->dst) < arg->mtu && 2072 (dst_mtu(&rt->dst) < arg->mtu &&
2074 dst_mtu(&rt->dst) == idev->cnf.mtu6))) { 2073 dst_mtu(&rt->dst) == idev->cnf.mtu6))) {
2075 dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu); 2074 dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu);
2076 dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, arg->mtu));
2077 } 2075 }
2078 return 0; 2076 return 0;
2079} 2077}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index fee076891646..20aa95e37359 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1521,7 +1521,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1521 1521
1522 tcp_mtup_init(newsk); 1522 tcp_mtup_init(newsk);
1523 tcp_sync_mss(newsk, dst_mtu(dst)); 1523 tcp_sync_mss(newsk, dst_mtu(dst));
1524 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 1524 newtp->advmss = dst_metric_advmss(dst);
1525 tcp_initialize_rcv_mss(newsk); 1525 tcp_initialize_rcv_mss(newsk);
1526 1526
1527 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; 1527 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;