aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-01-28 01:01:53 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-28 01:01:53 -0500
commita4daad6b0923030fbd3b00a01f570e4c3eef446b (patch)
treeb8e5b9a2110628503e57149f0bb2a4bb1bf3f027 /net/ipv4/route.c
parent8571a19c4ac140f1a507f3e7eb716892afa27109 (diff)
net: Pre-COW metrics for TCP.
TCP is going to record metrics for the connection, so pre-COW the route metrics at route cache entry creation time. This avoids several atomic operations that have to occur if we COW the metrics after the entry reaches global visibility. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 68cee358d9a3..dd57f4896736 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1857,6 +1857,28 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
1857 return mtu; 1857 return mtu;
1858} 1858}
1859 1859
1860static void rt_init_metrics(struct rtable *rt, struct fib_info *fi)
1861{
1862 if (!(rt->fl.flags & FLOWI_FLAG_PRECOW_METRICS)) {
1863 no_cow:
1864 rt->fi = fi;
1865 atomic_inc(&fi->fib_clntref);
1866 dst_init_metrics(&rt->dst, fi->fib_metrics, true);
1867 } else {
1868 struct inet_peer *peer;
1869
1870 if (!rt->peer)
1871 rt_bind_peer(rt, 1);
1872 peer = rt->peer;
1873 if (!peer)
1874 goto no_cow;
1875 if (inet_metrics_new(peer))
1876 memcpy(peer->metrics, fi->fib_metrics,
1877 sizeof(u32) * RTAX_MAX);
1878 dst_init_metrics(&rt->dst, peer->metrics, false);
1879 }
1880}
1881
1860static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) 1882static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
1861{ 1883{
1862 struct dst_entry *dst = &rt->dst; 1884 struct dst_entry *dst = &rt->dst;
@@ -1866,9 +1888,7 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
1866 if (FIB_RES_GW(*res) && 1888 if (FIB_RES_GW(*res) &&
1867 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) 1889 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
1868 rt->rt_gateway = FIB_RES_GW(*res); 1890 rt->rt_gateway = FIB_RES_GW(*res);
1869 rt->fi = fi; 1891 rt_init_metrics(rt, fi);
1870 atomic_inc(&fi->fib_clntref);
1871 dst_init_metrics(dst, fi->fib_metrics, true);
1872#ifdef CONFIG_IP_ROUTE_CLASSID 1892#ifdef CONFIG_IP_ROUTE_CLASSID
1873 dst->tclassid = FIB_RES_NH(*res).nh_tclassid; 1893 dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
1874#endif 1894#endif