aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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 /net/ipv4
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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/route.c55
-rw-r--r--net/ipv4/tcp_input.c22
3 files changed, 44 insertions, 35 deletions
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}