udp: Set NULL to udp_seq_afinfo.udp_table.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Mon, 14 Nov 2022 21:57:55 +0000 (13:57 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Nov 2022 09:43:35 +0000 (09:43 +0000)
We will soon introduce an optional per-netns hash table
for UDP.

This means we cannot use the global udp_seq_afinfo.udp_table
to fetch a UDP hash table.

Instead, set NULL to udp_seq_afinfo.udp_table for UDP and get
a proper table from net->ipv4.udp_table.

Note that we still need udp_seq_afinfo.udp_table for UDP LITE.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/udp.c
net/ipv6/udp.c

index 6206c27..a1a15eb 100644 (file)
@@ -2980,11 +2980,18 @@ EXPORT_SYMBOL(udp_prot);
 /* ------------------------------------------------------------------------ */
 #ifdef CONFIG_PROC_FS
 
+static struct udp_table *udp_get_table_afinfo(struct udp_seq_afinfo *afinfo,
+                                             struct net *net)
+{
+       return afinfo->udp_table ? : net->ipv4.udp_table;
+}
+
 static struct sock *udp_get_first(struct seq_file *seq, int start)
 {
        struct udp_iter_state *state = seq->private;
        struct net *net = seq_file_net(seq);
        struct udp_seq_afinfo *afinfo;
+       struct udp_table *udptable;
        struct sock *sk;
 
        if (state->bpf_seq_afinfo)
@@ -2992,9 +2999,11 @@ static struct sock *udp_get_first(struct seq_file *seq, int start)
        else
                afinfo = pde_data(file_inode(seq->file));
 
-       for (state->bucket = start; state->bucket <= afinfo->udp_table->mask;
+       udptable = udp_get_table_afinfo(afinfo, net);
+
+       for (state->bucket = start; state->bucket <= udptable->mask;
             ++state->bucket) {
-               struct udp_hslot *hslot = &afinfo->udp_table->hash[state->bucket];
+               struct udp_hslot *hslot = &udptable->hash[state->bucket];
 
                if (hlist_empty(&hslot->head))
                        continue;
@@ -3019,6 +3028,7 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
        struct udp_iter_state *state = seq->private;
        struct net *net = seq_file_net(seq);
        struct udp_seq_afinfo *afinfo;
+       struct udp_table *udptable;
 
        if (state->bpf_seq_afinfo)
                afinfo = state->bpf_seq_afinfo;
@@ -3032,8 +3042,11 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
                         sk->sk_family != afinfo->family)));
 
        if (!sk) {
-               if (state->bucket <= afinfo->udp_table->mask)
-                       spin_unlock_bh(&afinfo->udp_table->hash[state->bucket].lock);
+               udptable = udp_get_table_afinfo(afinfo, net);
+
+               if (state->bucket <= udptable->mask)
+                       spin_unlock_bh(&udptable->hash[state->bucket].lock);
+
                return udp_get_first(seq, state->bucket + 1);
        }
        return sk;
@@ -3076,14 +3089,17 @@ void udp_seq_stop(struct seq_file *seq, void *v)
 {
        struct udp_iter_state *state = seq->private;
        struct udp_seq_afinfo *afinfo;
+       struct udp_table *udptable;
 
        if (state->bpf_seq_afinfo)
                afinfo = state->bpf_seq_afinfo;
        else
                afinfo = pde_data(file_inode(seq->file));
 
-       if (state->bucket <= afinfo->udp_table->mask)
-               spin_unlock_bh(&afinfo->udp_table->hash[state->bucket].lock);
+       udptable = udp_get_table_afinfo(afinfo, seq_file_net(seq));
+
+       if (state->bucket <= udptable->mask)
+               spin_unlock_bh(&udptable->hash[state->bucket].lock);
 }
 EXPORT_SYMBOL(udp_seq_stop);
 
@@ -3196,7 +3212,7 @@ EXPORT_SYMBOL(udp_seq_ops);
 
 static struct udp_seq_afinfo udp4_seq_afinfo = {
        .family         = AF_INET,
-       .udp_table      = &udp_table,
+       .udp_table      = NULL,
 };
 
 static int __net_init udp4_proc_init_net(struct net *net)
@@ -3316,7 +3332,7 @@ static int bpf_iter_init_udp(void *priv_data, struct bpf_iter_aux_info *aux)
                return -ENOMEM;
 
        afinfo->family = AF_UNSPEC;
-       afinfo->udp_table = &udp_table;
+       afinfo->udp_table = NULL;
        st->bpf_seq_afinfo = afinfo;
        ret = bpf_iter_init_seq_net(priv_data, aux);
        if (ret)
index bbd6dc3..c3dee1f 100644 (file)
@@ -1724,7 +1724,7 @@ EXPORT_SYMBOL(udp6_seq_ops);
 
 static struct udp_seq_afinfo udp6_seq_afinfo = {
        .family         = AF_INET6,
-       .udp_table      = &udp_table,
+       .udp_table      = NULL,
 };
 
 int __net_init udp6_proc_init(struct net *net)