aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/flow.h3
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/route.h4
-rw-r--r--net/ipv4/route.c26
4 files changed, 36 insertions, 5 deletions
diff --git a/include/net/flow.h b/include/net/flow.h
index 240b7f356c71..1ae901f24436 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -48,7 +48,8 @@ struct flowi {
48 48
49 __u8 proto; 49 __u8 proto;
50 __u8 flags; 50 __u8 flags;
51#define FLOWI_FLAG_ANYSRC 0x01 51#define FLOWI_FLAG_ANYSRC 0x01
52#define FLOWI_FLAG_PRECOW_METRICS 0x02
52 union { 53 union {
53 struct { 54 struct {
54 __be16 sport; 55 __be16 sport;
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 8181498fa96c..6e6dfd757682 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -219,7 +219,13 @@ static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops
219 219
220static inline __u8 inet_sk_flowi_flags(const struct sock *sk) 220static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
221{ 221{
222 return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0; 222 __u8 flags = 0;
223
224 if (inet_sk(sk)->transparent)
225 flags |= FLOWI_FLAG_ANYSRC;
226 if (sk->sk_protocol == IPPROTO_TCP)
227 flags |= FLOWI_FLAG_PRECOW_METRICS;
228 return flags;
223} 229}
224 230
225#endif /* _INET_SOCK_H */ 231#endif /* _INET_SOCK_H */
diff --git a/include/net/route.h b/include/net/route.h
index 5677cbf0c6e6..e5864658dc76 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -182,6 +182,8 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
182 182
183 if (inet_sk(sk)->transparent) 183 if (inet_sk(sk)->transparent)
184 fl.flags |= FLOWI_FLAG_ANYSRC; 184 fl.flags |= FLOWI_FLAG_ANYSRC;
185 if (protocol == IPPROTO_TCP)
186 fl.flags |= FLOWI_FLAG_PRECOW_METRICS;
185 187
186 if (!dst || !src) { 188 if (!dst || !src) {
187 err = __ip_route_output_key(net, rp, &fl); 189 err = __ip_route_output_key(net, rp, &fl);
@@ -209,6 +211,8 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
209 fl.proto = protocol; 211 fl.proto = protocol;
210 if (inet_sk(sk)->transparent) 212 if (inet_sk(sk)->transparent)
211 fl.flags |= FLOWI_FLAG_ANYSRC; 213 fl.flags |= FLOWI_FLAG_ANYSRC;
214 if (protocol == IPPROTO_TCP)
215 fl.flags |= FLOWI_FLAG_PRECOW_METRICS;
212 ip_rt_put(*rp); 216 ip_rt_put(*rp);
213 *rp = NULL; 217 *rp = NULL;
214 security_sk_classify_flow(sk, &fl); 218 security_sk_classify_flow(sk, &fl);
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