History

net: prefer socket bound to interface when not in VRF

The commit 6da5b0f027a8 ("net: ensure unbound datagram socket to be chosen when not in a VRF") modified compute_score() so that a device match is always made, not just in the case of an l3mdev skb, then increments the score also for unbound sockets. This ensures that sockets bound to an l3mdev are never selected when not in a VRF. But as unbound and bound sockets are now scored equally, this results in the last opened socket being selected if there are matches in the default VRF for an unbound socket and a socket bound to a dev that is not an l3mdev. However, handling prior to this commit was to always select the bound socket in this case. Reinstate this handling by incrementing the score only for bound sockets. The required isolation due to choosing between an unbound socket and a socket bound to an l3mdev remains in place due to the device match always being made. The same approach is taken for compute_score() for stream sockets.

Mike Manning committed 5 years ago

Commit 8d6c4141 parent 7671b024 files · +8 −4Browse files

Unified · Split

4 files
  1. net/ipv4/inet_hashtables.c +3 −1
  2. net/ipv4/udp.c +2 −1
  3. net/ipv6/inet6_hashtables.c +1 −1
  4. net/ipv6/udp.c +2 −1
net/ipv4/inet_hashtables.c+3−1
@@ -242,8 +242,10 @@ static inline int compute_score(struct sock *sk, struct net *net, · 241 unmodified lines
242 242
243 if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))243 if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
244 return -1;244 return -1;
245 score = sk->sk_bound_dev_if ? 2 : 1;
245 246
246 score = sk->sk_family == PF_INET ? 2 : 1;247 if (sk->sk_family == PF_INET)
248 score++;
247 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())249 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
248 score++;250 score++;
249 }251 }
net/ipv4/udp.c+2−1
@@ -390,7 +390,8 @@ static int compute_score(struct sock *sk, struct net *net, · 389 unmodified lines
390 dif, sdif);390 dif, sdif);
391 if (!dev_match)391 if (!dev_match)
392 return -1;392 return -1;
393 score += 4;393 if (sk->sk_bound_dev_if)
394 score += 4;
394 395
395 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())396 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
396 score++;397 score++;
net/ipv6/inet6_hashtables.c+1−1
@@ -106,7 +106,7 @@ static inline int compute_score(struct sock *sk, struct net *net, · 105 unmodified lines
106 if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))106 if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
107 return -1;107 return -1;
108 108
109 score = 1;109 score = sk->sk_bound_dev_if ? 2 : 1;
110 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())110 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
111 score++;111 score++;
112 }112 }
net/ipv6/udp.c+2−1
@@ -133,7 +133,8 @@ static int compute_score(struct sock *sk, struct net *net, · 132 unmodified lines
133 dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);133 dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);
134 if (!dev_match)134 if (!dev_match)
135 return -1;135 return -1;
136 score++;136 if (sk->sk_bound_dev_if)
137 score++;
137 138
138 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())139 if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
139 score++;140 score++;