|
@@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(udp_lib_unhash);
|
|
EXPORT_SYMBOL(udp_lib_unhash);
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * inet_rcv_saddr was changed, we must rehash secondary hash
|
|
|
|
+ */
|
|
|
|
+void udp_lib_rehash(struct sock *sk, u16 newhash)
|
|
|
|
+{
|
|
|
|
+ if (sk_hashed(sk)) {
|
|
|
|
+ struct udp_table *udptable = sk->sk_prot->h.udp_table;
|
|
|
|
+ struct udp_hslot *hslot, *hslot2, *nhslot2;
|
|
|
|
+
|
|
|
|
+ hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
|
|
|
|
+ nhslot2 = udp_hashslot2(udptable, newhash);
|
|
|
|
+ udp_sk(sk)->udp_portaddr_hash = newhash;
|
|
|
|
+ if (hslot2 != nhslot2) {
|
|
|
|
+ hslot = udp_hashslot(udptable, sock_net(sk),
|
|
|
|
+ udp_sk(sk)->udp_port_hash);
|
|
|
|
+ /* we must lock primary chain too */
|
|
|
|
+ spin_lock_bh(&hslot->lock);
|
|
|
|
+
|
|
|
|
+ spin_lock(&hslot2->lock);
|
|
|
|
+ hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
|
|
|
|
+ hslot2->count--;
|
|
|
|
+ spin_unlock(&hslot2->lock);
|
|
|
|
+
|
|
|
|
+ spin_lock(&nhslot2->lock);
|
|
|
|
+ hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
|
|
|
|
+ &nhslot2->head);
|
|
|
|
+ nhslot2->count++;
|
|
|
|
+ spin_unlock(&nhslot2->lock);
|
|
|
|
+
|
|
|
|
+ spin_unlock_bh(&hslot->lock);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(udp_lib_rehash);
|
|
|
|
+
|
|
|
|
+static void udp_v4_rehash(struct sock *sk)
|
|
|
|
+{
|
|
|
|
+ u16 new_hash = udp4_portaddr_hash(sock_net(sk),
|
|
|
|
+ inet_sk(sk)->inet_rcv_saddr,
|
|
|
|
+ inet_sk(sk)->inet_num);
|
|
|
|
+ udp_lib_rehash(sk, new_hash);
|
|
|
|
+}
|
|
|
|
+
|
|
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
{
|
|
{
|
|
int rc;
|
|
int rc;
|
|
@@ -1843,6 +1886,7 @@ struct proto udp_prot = {
|
|
.backlog_rcv = __udp_queue_rcv_skb,
|
|
.backlog_rcv = __udp_queue_rcv_skb,
|
|
.hash = udp_lib_hash,
|
|
.hash = udp_lib_hash,
|
|
.unhash = udp_lib_unhash,
|
|
.unhash = udp_lib_unhash,
|
|
|
|
+ .rehash = udp_v4_rehash,
|
|
.get_port = udp_v4_get_port,
|
|
.get_port = udp_v4_get_port,
|
|
.memory_allocated = &udp_memory_allocated,
|
|
.memory_allocated = &udp_memory_allocated,
|
|
.sysctl_mem = sysctl_udp_mem,
|
|
.sysctl_mem = sysctl_udp_mem,
|