net: Abstract default ADVMSS behind an accessor.
[cascardo/linux.git] / net / ipv4 / route.c
index ec2333f..8099733 100644 (file)
@@ -139,6 +139,7 @@ static unsigned long expires_ljiffies;
  */
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
+static unsigned int     ipv4_default_advmss(const struct dst_entry *dst);
 static void             ipv4_dst_destroy(struct dst_entry *dst);
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
 static void             ipv4_link_failure(struct sk_buff *skb);
@@ -155,6 +156,7 @@ static struct dst_ops ipv4_dst_ops = {
        .protocol =             cpu_to_be16(ETH_P_IP),
        .gc =                   rt_garbage_collect,
        .check =                ipv4_dst_check,
+       .default_advmss =       ipv4_default_advmss,
        .destroy =              ipv4_dst_destroy,
        .ifdown =               ipv4_dst_ifdown,
        .negative_advice =      ipv4_negative_advice,
@@ -383,8 +385,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
                        (__force u32)r->rt_gateway,
                        r->rt_flags, atomic_read(&r->dst.__refcnt),
                        r->dst.__use, 0, (__force u32)r->rt_src,
-                       (dst_metric(&r->dst, RTAX_ADVMSS) ?
-                            (int)dst_metric(&r->dst, RTAX_ADVMSS) + 40 : 0),
+                       dst_metric_advmss(&r->dst) + 40,
                        dst_metric(&r->dst, RTAX_WINDOW),
                        (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +
                              dst_metric(&r->dst, RTAX_RTTVAR)),
@@ -1289,7 +1290,7 @@ void rt_bind_peer(struct rtable *rt, int create)
 {
        struct inet_peer *peer;
 
-       peer = inet_getpeer(rt->rt_dst, create);
+       peer = inet_getpeer_v4(rt->rt_dst, create);
 
        if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL)
                inet_putpeer(peer);
@@ -1686,11 +1687,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
                                        if (mtu < dst_mtu(&rth->dst)) {
                                                dst_confirm(&rth->dst);
                                                if (mtu < ip_rt_min_pmtu) {
+                                                       u32 lock = dst_metric(&rth->dst,
+                                                                             RTAX_LOCK);
                                                        mtu = ip_rt_min_pmtu;
-                                                       rth->dst.metrics[RTAX_LOCK-1] |=
-                                                               (1 << RTAX_MTU);
+                                                       lock |= (1 << RTAX_MTU);
+                                                       dst_metric_set(&rth->dst, RTAX_LOCK,
+                                                                      lock);
                                                }
-                                               rth->dst.metrics[RTAX_MTU-1] = mtu;
+                                               dst_metric_set(&rth->dst, RTAX_MTU, mtu);
                                                dst_set_expires(&rth->dst,
                                                        ip_rt_mtu_expires);
                                        }
@@ -1708,10 +1712,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
        if (dst_mtu(dst) > mtu && mtu >= 68 &&
            !(dst_metric_locked(dst, RTAX_MTU))) {
                if (mtu < ip_rt_min_pmtu) {
+                       u32 lock = dst_metric(dst, RTAX_LOCK);
                        mtu = ip_rt_min_pmtu;
-                       dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU);
+                       dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU));
                }
-               dst->metrics[RTAX_MTU-1] = mtu;
+               dst_metric_set(dst, RTAX_MTU, mtu);
                dst_set_expires(dst, ip_rt_mtu_expires);
                call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
        }
@@ -1794,38 +1799,46 @@ static void set_class_tag(struct rtable *rt, u32 tag)
 }
 #endif
 
+static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
+{
+       unsigned int advmss = dst_metric_raw(dst, RTAX_ADVMSS);
+
+       if (advmss == 0) {
+               advmss = max_t(unsigned int, dst->dev->mtu - 40,
+                              ip_rt_min_advmss);
+               if (advmss > 65535 - 40)
+                       advmss = 65535 - 40;
+       }
+       return advmss;
+}
+
 static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
 {
+       struct dst_entry *dst = &rt->dst;
        struct fib_info *fi = res->fi;
 
        if (fi) {
                if (FIB_RES_GW(*res) &&
                    FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
                        rt->rt_gateway = FIB_RES_GW(*res);
-               memcpy(rt->dst.metrics, fi->fib_metrics,
-                      sizeof(rt->dst.metrics));
+               dst_import_metrics(dst, fi->fib_metrics);
                if (fi->fib_mtu == 0) {
-                       rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu;
-                       if (dst_metric_locked(&rt->dst, RTAX_MTU) &&
+                       dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
+                       if (dst_metric_locked(dst, RTAX_MTU) &&
                            rt->rt_gateway != rt->rt_dst &&
-                           rt->dst.dev->mtu > 576)
-                               rt->dst.metrics[RTAX_MTU-1] = 576;
+                           dst->dev->mtu > 576)
+                               dst_metric_set(dst, RTAX_MTU, 576);
                }
 #ifdef CONFIG_NET_CLS_ROUTE
-               rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
+               dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
 #endif
        } else
-               rt->dst.metrics[RTAX_MTU-1]= rt->dst.dev->mtu;
-
-       if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0)
-               rt->dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
-       if (dst_mtu(&rt->dst) > IP_MAX_MTU)
-               rt->dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
-       if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0)
-               rt->dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->dst.dev->mtu - 40,
-                                      ip_rt_min_advmss);
-       if (dst_metric(&rt->dst, RTAX_ADVMSS) > 65535 - 40)
-               rt->dst.metrics[RTAX_ADVMSS-1] = 65535 - 40;
+               dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
+
+       if (dst_mtu(dst) > IP_MAX_MTU)
+               dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU);
+       if (dst_metric_raw(dst, RTAX_ADVMSS) > 65535 - 40)
+               dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40);
 
 #ifdef CONFIG_NET_CLS_ROUTE
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -2720,7 +2733,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
                new->__use = 1;
                new->input = dst_discard;
                new->output = dst_discard;
-               memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
+               dst_copy_metrics(new, &ort->dst);
 
                new->dev = ort->dst.dev;
                if (new->dev)
@@ -2827,7 +2840,7 @@ static int rt_fill_info(struct net *net,
        if (rt->rt_dst != rt->rt_gateway)
                NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway);
 
-       if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0)
+       if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
                goto nla_put_failure;
 
        if (rt->fl.mark)