aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;