aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/dst.h26
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_netfilter.c2
-rw-r--r--net/decnet/dn_route.c13
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/route.c55
-rw-r--r--net/ipv4/tcp_input.c22
-rw-r--r--net/ipv6/ndisc.c5
-rw-r--r--net/ipv6/route.c66
-rw-r--r--net/xfrm/xfrm_policy.c6
10 files changed, 118 insertions, 81 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index a5bd72646d65..85dee3a57b9b 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -70,7 +70,7 @@ struct dst_entry {
70 70
71 struct dst_ops *ops; 71 struct dst_ops *ops;
72 72
73 u32 metrics[RTAX_MAX]; 73 u32 _metrics[RTAX_MAX];
74 74
75#ifdef CONFIG_NET_CLS_ROUTE 75#ifdef CONFIG_NET_CLS_ROUTE
76 __u32 tclassid; 76 __u32 tclassid;
@@ -106,7 +106,27 @@ struct dst_entry {
106static inline u32 106static inline u32
107dst_metric(const struct dst_entry *dst, int metric) 107dst_metric(const struct dst_entry *dst, int metric)
108{ 108{
109 return dst->metrics[metric-1]; 109 return dst->_metrics[metric-1];
110}
111
112static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
113{
114 dst->_metrics[metric-1] = val;
115}
116
117static inline void dst_import_metrics(struct dst_entry *dst, const u32 *src_metrics)
118{
119 memcpy(dst->_metrics, src_metrics, RTAX_MAX * sizeof(u32));
120}
121
122static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
123{
124 dst_import_metrics(dest, src->_metrics);
125}
126
127static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
128{
129 return dst->_metrics;
110} 130}
111 131
112static inline u32 132static inline u32
@@ -134,7 +154,7 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr
134static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, 154static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric,
135 unsigned long rtt) 155 unsigned long rtt)
136{ 156{
137 dst->metrics[metric-1] = jiffies_to_msecs(rtt); 157 dst_metric_set(dst, metric, jiffies_to_msecs(rtt));
138} 158}
139 159
140static inline u32 160static inline u32
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 17cb0b633576..556443566e9c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -141,7 +141,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
141 141
142#ifdef CONFIG_BRIDGE_NETFILTER 142#ifdef CONFIG_BRIDGE_NETFILTER
143 /* remember the MTU in the rtable for PMTU */ 143 /* remember the MTU in the rtable for PMTU */
144 br->fake_rtable.dst.metrics[RTAX_MTU - 1] = new_mtu; 144 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
145#endif 145#endif
146 146
147 return 0; 147 return 0;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 6e1392093911..16f5c333596a 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -124,7 +124,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
124 atomic_set(&rt->dst.__refcnt, 1); 124 atomic_set(&rt->dst.__refcnt, 1);
125 rt->dst.dev = br->dev; 125 rt->dst.dev = br->dev;
126 rt->dst.path = &rt->dst; 126 rt->dst.path = &rt->dst;
127 rt->dst.metrics[RTAX_MTU - 1] = 1500; 127 dst_metric_set(&rt->dst, RTAX_MTU, 1500);
128 rt->dst.flags = DST_NOXFRM; 128 rt->dst.flags = DST_NOXFRM;
129 rt->dst.ops = &fake_dst_ops; 129 rt->dst.ops = &fake_dst_ops;
130} 130}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 8280e43c8861..e2e926841fe6 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -240,13 +240,13 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
240 240
241 if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { 241 if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) {
242 if (!(dst_metric_locked(dst, RTAX_MTU))) { 242 if (!(dst_metric_locked(dst, RTAX_MTU))) {
243 dst->metrics[RTAX_MTU-1] = mtu; 243 dst_metric_set(dst, RTAX_MTU, mtu);
244 dst_set_expires(dst, dn_rt_mtu_expires); 244 dst_set_expires(dst, dn_rt_mtu_expires);
245 } 245 }
246 if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { 246 if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
247 u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; 247 u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
248 if (dst_metric(dst, RTAX_ADVMSS) > mss) 248 if (dst_metric(dst, RTAX_ADVMSS) > mss)
249 dst->metrics[RTAX_ADVMSS-1] = mss; 249 dst_metric_set(dst, RTAX_ADVMSS, mss);
250 } 250 }
251 } 251 }
252} 252}
@@ -806,8 +806,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
806 if (DN_FIB_RES_GW(*res) && 806 if (DN_FIB_RES_GW(*res) &&
807 DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) 807 DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
808 rt->rt_gateway = DN_FIB_RES_GW(*res); 808 rt->rt_gateway = DN_FIB_RES_GW(*res);
809 memcpy(rt->dst.metrics, fi->fib_metrics, 809 dst_import_metrics(&rt->dst, fi->fib_metrics);
810 sizeof(rt->dst.metrics));
811 } 810 }
812 rt->rt_type = res->type; 811 rt->rt_type = res->type;
813 812
@@ -820,11 +819,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
820 819
821 if (dst_metric(&rt->dst, RTAX_MTU) == 0 || 820 if (dst_metric(&rt->dst, RTAX_MTU) == 0 ||
822 dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) 821 dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
823 rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; 822 dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu);
824 mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); 823 mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst));
825 if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 || 824 if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 ||
826 dst_metric(&rt->dst, RTAX_ADVMSS) > mss) 825 dst_metric(&rt->dst, RTAX_ADVMSS) > mss)
827 rt->dst.metrics[RTAX_ADVMSS-1] = mss; 826 dst_metric_set(&rt->dst, RTAX_ADVMSS, mss);
828 return 0; 827 return 0;
829} 828}
830 829
@@ -1502,7 +1501,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1502 RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); 1501 RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src);
1503 if (rt->rt_daddr != rt->rt_gateway) 1502 if (rt->rt_daddr != rt->rt_gateway)
1504 RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); 1503 RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
1505 if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) 1504 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
1506 goto rtattr_failure; 1505 goto rtattr_failure;
1507 expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; 1506 expires = rt->dst.expires ? rt->dst.expires - jiffies : 0;
1508 if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, 1507 if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires,
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 258c98d5fa79..ff4e7a4e33ed 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -818,7 +818,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
818 !ipv4_is_multicast(tunnel->parms.iph.daddr)) || 818 !ipv4_is_multicast(tunnel->parms.iph.daddr)) ||
819 rt6->rt6i_dst.plen == 128) { 819 rt6->rt6i_dst.plen == 128) {
820 rt6->rt6i_flags |= RTF_MODIFIED; 820 rt6->rt6i_flags |= RTF_MODIFIED;
821 skb_dst(skb)->metrics[RTAX_MTU-1] = mtu; 821 dst_metric_set(skb_dst(skb), RTAX_MTU, mtu);
822 } 822 }
823 } 823 }
824 824
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3843c2dfde82..26ac396eaa5e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1686,11 +1686,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
1686 if (mtu < dst_mtu(&rth->dst)) { 1686 if (mtu < dst_mtu(&rth->dst)) {
1687 dst_confirm(&rth->dst); 1687 dst_confirm(&rth->dst);
1688 if (mtu < ip_rt_min_pmtu) { 1688 if (mtu < ip_rt_min_pmtu) {
1689 u32 lock = dst_metric(&rth->dst,
1690 RTAX_LOCK);
1689 mtu = ip_rt_min_pmtu; 1691 mtu = ip_rt_min_pmtu;
1690 rth->dst.metrics[RTAX_LOCK-1] |= 1692 lock |= (1 << RTAX_MTU);
1691 (1 << RTAX_MTU); 1693 dst_metric_set(&rth->dst, RTAX_LOCK,
1694 lock);
1692 } 1695 }
1693 rth->dst.metrics[RTAX_MTU-1] = mtu; 1696 dst_metric_set(&rth->dst, RTAX_MTU, mtu);
1694 dst_set_expires(&rth->dst, 1697 dst_set_expires(&rth->dst,
1695 ip_rt_mtu_expires); 1698 ip_rt_mtu_expires);
1696 } 1699 }
@@ -1708,10 +1711,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1708 if (dst_mtu(dst) > mtu && mtu >= 68 && 1711 if (dst_mtu(dst) > mtu && mtu >= 68 &&
1709 !(dst_metric_locked(dst, RTAX_MTU))) { 1712 !(dst_metric_locked(dst, RTAX_MTU))) {
1710 if (mtu < ip_rt_min_pmtu) { 1713 if (mtu < ip_rt_min_pmtu) {
1714 u32 lock = dst_metric(dst, RTAX_LOCK);
1711 mtu = ip_rt_min_pmtu; 1715 mtu = ip_rt_min_pmtu;
1712 dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU); 1716 dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU));
1713 } 1717 }
1714 dst->metrics[RTAX_MTU-1] = mtu; 1718 dst_metric_set(dst, RTAX_MTU, mtu);
1715 dst_set_expires(dst, ip_rt_mtu_expires); 1719 dst_set_expires(dst, ip_rt_mtu_expires);
1716 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); 1720 call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
1717 } 1721 }
@@ -1796,36 +1800,37 @@ static void set_class_tag(struct rtable *rt, u32 tag)
1796 1800
1797static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) 1801static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
1798{ 1802{
1803 struct dst_entry *dst = &rt->dst;
1799 struct fib_info *fi = res->fi; 1804 struct fib_info *fi = res->fi;
1800 1805
1801 if (fi) { 1806 if (fi) {
1802 if (FIB_RES_GW(*res) && 1807 if (FIB_RES_GW(*res) &&
1803 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) 1808 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
1804 rt->rt_gateway = FIB_RES_GW(*res); 1809 rt->rt_gateway = FIB_RES_GW(*res);
1805 memcpy(rt->dst.metrics, fi->fib_metrics, 1810 dst_import_metrics(dst, fi->fib_metrics);
1806 sizeof(rt->dst.metrics));
1807 if (fi->fib_mtu == 0) { 1811 if (fi->fib_mtu == 0) {
1808 rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; 1812 dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
1809 if (dst_metric_locked(&rt->dst, RTAX_MTU) && 1813 if (dst_metric_locked(dst, RTAX_MTU) &&
1810 rt->rt_gateway != rt->rt_dst && 1814 rt->rt_gateway != rt->rt_dst &&
1811 rt->dst.dev->mtu > 576) 1815 dst->dev->mtu > 576)
1812 rt->dst.metrics[RTAX_MTU-1] = 576; 1816 dst_metric_set(dst, RTAX_MTU, 576);
1813 } 1817 }
1814#ifdef CONFIG_NET_CLS_ROUTE 1818#ifdef CONFIG_NET_CLS_ROUTE
1815 rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid; 1819 dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
1816#endif 1820#endif
1817 } else 1821 } else
1818 rt->dst.metrics[RTAX_MTU-1]= rt->dst.dev->mtu; 1822 dst_metric_set(dst, RTAX_MTU, dst->dev->mtu);
1819 1823
1820 if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) 1824 if (dst_metric(dst, RTAX_HOPLIMIT) == 0)
1821 rt->dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl; 1825 dst_metric_set(dst, RTAX_HOPLIMIT, sysctl_ip_default_ttl);
1822 if (dst_mtu(&rt->dst) > IP_MAX_MTU) 1826 if (dst_mtu(dst) > IP_MAX_MTU)
1823 rt->dst.metrics[RTAX_MTU-1] = IP_MAX_MTU; 1827 dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU);
1824 if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0) 1828 if (dst_metric(dst, RTAX_ADVMSS) == 0)
1825 rt->dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->dst.dev->mtu - 40, 1829 dst_metric_set(dst, RTAX_ADVMSS,
1826 ip_rt_min_advmss); 1830 max_t(unsigned int, dst->dev->mtu - 40,
1827 if (dst_metric(&rt->dst, RTAX_ADVMSS) > 65535 - 40) 1831 ip_rt_min_advmss));
1828 rt->dst.metrics[RTAX_ADVMSS-1] = 65535 - 40; 1832 if (dst_metric(dst, RTAX_ADVMSS) > 65535 - 40)
1833 dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40);
1829 1834
1830#ifdef CONFIG_NET_CLS_ROUTE 1835#ifdef CONFIG_NET_CLS_ROUTE
1831#ifdef CONFIG_IP_MULTIPLE_TABLES 1836#ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -2720,7 +2725,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
2720 new->__use = 1; 2725 new->__use = 1;
2721 new->input = dst_discard; 2726 new->input = dst_discard;
2722 new->output = dst_discard; 2727 new->output = dst_discard;
2723 memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); 2728 dst_copy_metrics(new, &ort->dst);
2724 2729
2725 new->dev = ort->dst.dev; 2730 new->dev = ort->dst.dev;
2726 if (new->dev) 2731 if (new->dev)
@@ -2827,7 +2832,7 @@ static int rt_fill_info(struct net *net,
2827 if (rt->rt_dst != rt->rt_gateway) 2832 if (rt->rt_dst != rt->rt_gateway)
2828 NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); 2833 NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway);
2829 2834
2830 if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) 2835 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2831 goto nla_put_failure; 2836 goto nla_put_failure;
2832 2837
2833 if (rt->fl.mark) 2838 if (rt->fl.mark)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 6d8ab1c4efc3..824e8c8a17ad 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -734,7 +734,7 @@ void tcp_update_metrics(struct sock *sk)
734 * Reset our results. 734 * Reset our results.
735 */ 735 */
736 if (!(dst_metric_locked(dst, RTAX_RTT))) 736 if (!(dst_metric_locked(dst, RTAX_RTT)))
737 dst->metrics[RTAX_RTT - 1] = 0; 737 dst_metric_set(dst, RTAX_RTT, 0);
738 return; 738 return;
739 } 739 }
740 740
@@ -776,34 +776,38 @@ void tcp_update_metrics(struct sock *sk)
776 if (dst_metric(dst, RTAX_SSTHRESH) && 776 if (dst_metric(dst, RTAX_SSTHRESH) &&
777 !dst_metric_locked(dst, RTAX_SSTHRESH) && 777 !dst_metric_locked(dst, RTAX_SSTHRESH) &&
778 (tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH)) 778 (tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH))
779 dst->metrics[RTAX_SSTHRESH-1] = tp->snd_cwnd >> 1; 779 dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_cwnd >> 1);
780 if (!dst_metric_locked(dst, RTAX_CWND) && 780 if (!dst_metric_locked(dst, RTAX_CWND) &&
781 tp->snd_cwnd > dst_metric(dst, RTAX_CWND)) 781 tp->snd_cwnd > dst_metric(dst, RTAX_CWND))
782 dst->metrics[RTAX_CWND - 1] = tp->snd_cwnd; 782 dst_metric_set(dst, RTAX_CWND, tp->snd_cwnd);
783 } else if (tp->snd_cwnd > tp->snd_ssthresh && 783 } else if (tp->snd_cwnd > tp->snd_ssthresh &&
784 icsk->icsk_ca_state == TCP_CA_Open) { 784 icsk->icsk_ca_state == TCP_CA_Open) {
785 /* Cong. avoidance phase, cwnd is reliable. */ 785 /* Cong. avoidance phase, cwnd is reliable. */
786 if (!dst_metric_locked(dst, RTAX_SSTHRESH)) 786 if (!dst_metric_locked(dst, RTAX_SSTHRESH))
787 dst->metrics[RTAX_SSTHRESH-1] = 787 dst_metric_set(dst, RTAX_SSTHRESH,
788 max(tp->snd_cwnd >> 1, tp->snd_ssthresh); 788 max(tp->snd_cwnd >> 1, tp->snd_ssthresh));
789 if (!dst_metric_locked(dst, RTAX_CWND)) 789 if (!dst_metric_locked(dst, RTAX_CWND))
790 dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_cwnd) >> 1; 790 dst_metric_set(dst, RTAX_CWND,
791 (dst_metric(dst, RTAX_CWND) +
792 tp->snd_cwnd) >> 1);
791 } else { 793 } else {
792 /* Else slow start did not finish, cwnd is non-sense, 794 /* Else slow start did not finish, cwnd is non-sense,
793 ssthresh may be also invalid. 795 ssthresh may be also invalid.
794 */ 796 */
795 if (!dst_metric_locked(dst, RTAX_CWND)) 797 if (!dst_metric_locked(dst, RTAX_CWND))
796 dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_ssthresh) >> 1; 798 dst_metric_set(dst, RTAX_CWND,
799 (dst_metric(dst, RTAX_CWND) +
800 tp->snd_ssthresh) >> 1);
797 if (dst_metric(dst, RTAX_SSTHRESH) && 801 if (dst_metric(dst, RTAX_SSTHRESH) &&
798 !dst_metric_locked(dst, RTAX_SSTHRESH) && 802 !dst_metric_locked(dst, RTAX_SSTHRESH) &&
799 tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH)) 803 tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH))
800 dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh; 804 dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_ssthresh);
801 } 805 }
802 806
803 if (!dst_metric_locked(dst, RTAX_REORDERING)) { 807 if (!dst_metric_locked(dst, RTAX_REORDERING)) {
804 if (dst_metric(dst, RTAX_REORDERING) < tp->reordering && 808 if (dst_metric(dst, RTAX_REORDERING) < tp->reordering &&
805 tp->reordering != sysctl_tcp_reordering) 809 tp->reordering != sysctl_tcp_reordering)
806 dst->metrics[RTAX_REORDERING-1] = tp->reordering; 810 dst_metric_set(dst, RTAX_REORDERING, tp->reordering);
807 } 811 }
808 } 812 }
809} 813}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index e18f84130203..2342545a5ee9 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1259,7 +1259,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
1259 if (ra_msg->icmph.icmp6_hop_limit) { 1259 if (ra_msg->icmph.icmp6_hop_limit) {
1260 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; 1260 in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
1261 if (rt) 1261 if (rt)
1262 rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; 1262 dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
1263 ra_msg->icmph.icmp6_hop_limit);
1263 } 1264 }
1264 1265
1265skip_defrtr: 1266skip_defrtr:
@@ -1377,7 +1378,7 @@ skip_linkparms:
1377 in6_dev->cnf.mtu6 = mtu; 1378 in6_dev->cnf.mtu6 = mtu;
1378 1379
1379 if (rt) 1380 if (rt)
1380 rt->dst.metrics[RTAX_MTU-1] = mtu; 1381 dst_metric_set(&rt->dst, RTAX_MTU, mtu);
1381 1382
1382 rt6_mtu_change(skb->dev, mtu); 1383 rt6_mtu_change(skb->dev, mtu);
1383 } 1384 }
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;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 044e77898512..6e50ccd8c532 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1433,7 +1433,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1433 } 1433 }
1434 1434
1435 xdst->route = dst; 1435 xdst->route = dst;
1436 memcpy(&dst1->metrics, &dst->metrics, sizeof(dst->metrics)); 1436 dst_copy_metrics(dst1, dst);
1437 1437
1438 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 1438 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
1439 family = xfrm[i]->props.family; 1439 family = xfrm[i]->props.family;
@@ -2271,7 +2271,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst)
2271 if (pmtu > route_mtu_cached) 2271 if (pmtu > route_mtu_cached)
2272 pmtu = route_mtu_cached; 2272 pmtu = route_mtu_cached;
2273 2273
2274 dst->metrics[RTAX_MTU-1] = pmtu; 2274 dst_metric_set(dst, RTAX_MTU, pmtu);
2275 } while ((dst = dst->next)); 2275 } while ((dst = dst->next));
2276} 2276}
2277 2277
@@ -2349,7 +2349,7 @@ static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
2349 mtu = xfrm_state_mtu(dst->xfrm, mtu); 2349 mtu = xfrm_state_mtu(dst->xfrm, mtu);
2350 if (mtu > last->route_mtu_cached) 2350 if (mtu > last->route_mtu_cached)
2351 mtu = last->route_mtu_cached; 2351 mtu = last->route_mtu_cached;
2352 dst->metrics[RTAX_MTU-1] = mtu; 2352 dst_metric_set(dst, RTAX_MTU, mtu);
2353 2353
2354 if (last == first) 2354 if (last == first)
2355 break; 2355 break;