summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Chevallier <maxime.chevallier@bootlin.com>2019-03-16 14:41:30 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-03 06:24:15 +0200
commit936a9180e81763a368adb92b6235edd5d5a67ca1 (patch)
tree1e854691b525f39bd72277e4b7d875a3db034973
parent65a1ff925de6a83c33e15f4160a858ceee093a30 (diff)
downloadlinux-stable-936a9180e81763a368adb92b6235edd5d5a67ca1.tar.gz
linux-stable-936a9180e81763a368adb92b6235edd5d5a67ca1.tar.bz2
linux-stable-936a9180e81763a368adb92b6235edd5d5a67ca1.zip
packets: Always register packet sk in the same order
[ Upstream commit a4dc6a49156b1f8d6e17251ffda17c9e6a5db78a ] When using fanouts with AF_PACKET, the demux functions such as fanout_demux_cpu will return an index in the fanout socket array, which corresponds to the selected socket. The ordering of this array depends on the order the sockets were added to a given fanout group, so for FANOUT_CPU this means sockets are bound to cpus in the order they are configured, which is OK. However, when stopping then restarting the interface these sockets are bound to, the sockets are reassigned to the fanout group in the reverse order, due to the fact that they were inserted at the head of the interface's AF_PACKET socket list. This means that traffic that was directed to the first socket in the fanout group is now directed to the last one after an interface restart. In the case of FANOUT_CPU, traffic from CPU0 will be directed to the socket that used to receive traffic from the last CPU after an interface restart. This commit introduces a helper to add a socket at the tail of a list, then uses it to register AF_PACKET sockets. Note that this changes the order in which sockets are listed in /proc and with sock_diag. Fixes: dc99f600698d ("packet: Add fanout support") Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/net/sock.h6
-rw-r--r--net/packet/af_packet.c2
2 files changed, 7 insertions, 1 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 15bb04dec40e..116308632fae 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -650,6 +650,12 @@ static inline void sk_add_node_rcu(struct sock *sk, struct hlist_head *list)
hlist_add_head_rcu(&sk->sk_node, list);
}
+static inline void sk_add_node_tail_rcu(struct sock *sk, struct hlist_head *list)
+{
+ sock_hold(sk);
+ hlist_add_tail_rcu(&sk->sk_node, list);
+}
+
static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
{
hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8d48c7816d7e..522d4ca715c9 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3278,7 +3278,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
}
mutex_lock(&net->packet.sklist_lock);
- sk_add_node_rcu(sk, &net->packet.sklist);
+ sk_add_node_tail_rcu(sk, &net->packet.sklist);
mutex_unlock(&net->packet.sklist_lock);
preempt_disable();