@@ -1732,22 +1732,12 @@ static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
}
-static inline u32 net_tx_rndhash(void)
-{
- u32 v = prandom_u32();
-
- return v ?: 1;
-}
-
-static inline void sk_set_txhash(struct sock *sk)
-{
- sk->sk_txhash = net_tx_rndhash();
-}
-
static inline void sk_rethink_txhash(struct sock *sk)
{
- if (sk->sk_txhash)
- sk_set_txhash(sk);
+ if (sk->sk_txhash) {
+ u32 v = prandom_u32();
+ sk->sk_txhash = v ?: 1;
+ }
}
static inline struct dst_entry *
@@ -1840,7 +1840,7 @@ struct tcp_request_sock_ops {
__u16 *mss);
#endif
struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
- const struct request_sock *req);
+ struct request_sock *req);
u32 (*init_seq)(const struct sk_buff *skb);
u32 (*init_ts_off)(const struct net *net, const struct sk_buff *skb);
int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
@@ -74,7 +74,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
inet->inet_daddr = fl4->daddr;
inet->inet_dport = usin->sin_port;
sk->sk_state = TCP_ESTABLISHED;
- sk_set_txhash(sk);
+ sk->sk_txhash = get_hash_from_flowi4(fl4);
inet->inet_id = jiffies;
sk_dst_set(sk, &rt->dst);
@@ -335,7 +335,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
treq->rcv_isn = ntohl(th->seq) - 1;
treq->snt_isn = cookie;
treq->ts_off = 0;
- treq->txhash = net_tx_rndhash();
req->mss = mss;
ireq->ir_num = ntohs(th->dest);
ireq->ir_rmt_port = th->source;
@@ -376,6 +375,9 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
opt->srr ? opt->faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+
+ treq->txhash = get_hash_from_flowi4(&fl4);
+
rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt)) {
reqsk_free(req);
@@ -6289,7 +6289,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
}
tcp_rsk(req)->snt_isn = isn;
- tcp_rsk(req)->txhash = net_tx_rndhash();
tcp_openreq_init_rwin(req, sk, dst);
if (!want_cookie) {
tcp_reqsk_record_syn(sk, req, skb);
@@ -222,7 +222,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (err)
goto failure;
- sk_set_txhash(sk);
+ sk->sk_txhash = get_hash_from_flowi4(fl4);
rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
inet->inet_sport, inet->inet_dport, sk);
@@ -871,8 +871,12 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
struct sk_buff *skb;
/* First, grab a route. */
- if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
- return -1;
+ if (!dst) {
+ if ((dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
+ return -1;
+
+ tcp_rsk(req)->txhash = get_hash_from_flowi4(&fl4);
+ }
skb = tcp_make_synack(sk, dst, req, foc, synack_type);
@@ -1278,9 +1282,12 @@ static void tcp_v4_init_req(struct request_sock *req,
static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
struct flowi *fl,
- const struct request_sock *req)
+ struct request_sock *req)
{
- return inet_csk_route_req(sk, &fl->u.ip4, req);
+ struct dst_entry *dst = inet_csk_route_req(sk, &fl->u.ip4, req);
+ if (dst)
+ tcp_rsk(req)->txhash = get_hash_from_flowi4(&fl->u.ip4);
+ return dst;
}
struct request_sock_ops tcp_request_sock_ops __read_mostly = {
@@ -3750,7 +3750,6 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)
struct flowi fl;
int res;
- tcp_rsk(req)->txhash = net_tx_rndhash();
res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL);
if (!res) {
__TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS);
@@ -150,6 +150,7 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_type;
int err;
__be32 fl6_flowlabel = 0;
+ struct flowi6 fl6;
if (usin->sin6_family == AF_INET) {
if (__ipv6_only_sock(sk))
@@ -260,7 +261,8 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
}
sk->sk_state = TCP_ESTABLISHED;
- sk_set_txhash(sk);
+ ip6_datagram_flow_key_init(&fl6, sk);
+ sk->sk_txhash = get_hash_from_flowi6(&fl6);
out:
return err;
}
@@ -216,7 +216,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
treq->rcv_isn = ntohl(th->seq) - 1;
treq->snt_isn = cookie;
treq->ts_off = 0;
- treq->txhash = net_tx_rndhash();
/*
* We need to lookup the dst_entry to get the correct window size.
@@ -238,6 +237,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
fl6.flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(&fl6));
+ treq->txhash = get_hash_from_flowi6(&fl6);
+
dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
if (IS_ERR(dst))
goto out_free;
@@ -286,7 +286,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (err)
goto late_failure;
- sk_set_txhash(sk);
+ sk->sk_txhash = get_hash_from_flowi6(&fl6);
if (likely(!tp->repair)) {
if (!tp->write_seq)
@@ -470,9 +470,13 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
int err = -ENOMEM;
/* First, grab a route. */
- if (!dst && (dst = inet6_csk_route_req(sk, fl6, req,
+ if (!dst) {
+ if ((dst = inet6_csk_route_req(sk, fl6, req,
IPPROTO_TCP)) == NULL)
- goto done;
+ goto done;
+
+ tcp_rsk(req)->txhash = get_hash_from_flowi6(fl6);
+ }
skb = tcp_make_synack(sk, dst, req, foc, synack_type);
@@ -743,9 +747,13 @@ static void tcp_v6_init_req(struct request_sock *req,
static struct dst_entry *tcp_v6_route_req(const struct sock *sk,
struct flowi *fl,
- const struct request_sock *req)
+ struct request_sock *req)
{
- return inet6_csk_route_req(sk, &fl->u.ip6, req, IPPROTO_TCP);
+ struct dst_entry *dst;
+ dst = inet6_csk_route_req(sk, &fl->u.ip6, req, IPPROTO_TCP);
+ if (dst)
+ tcp_rsk(req)->txhash = get_hash_from_flowi6(&fl->u.ip6);
+ return dst;
}
struct request_sock_ops tcp6_request_sock_ops __read_mostly = {