93
93
#include <linux/inet.h>
94
94
#include <linux/netdevice.h>
95
95
#include <linux/slab.h>
96
+ #include <linux/sock_diag.h>
96
97
#include <net/tcp_states.h>
97
98
#include <linux/skbuff.h>
98
99
#include <linux/proc_fs.h>
@@ -3393,34 +3394,51 @@ struct bpf_iter__udp {
3393
3394
3394
3395
union bpf_udp_iter_batch_item {
3395
3396
struct sock * sock ;
3397
+ __u64 cookie ;
3396
3398
};
3397
3399
3398
3400
struct bpf_udp_iter_state {
3399
3401
struct udp_iter_state state ;
3400
3402
unsigned int cur_sk ;
3401
3403
unsigned int end_sk ;
3402
3404
unsigned int max_sk ;
3403
- int offset ;
3404
3405
union bpf_udp_iter_batch_item * batch ;
3405
3406
bool st_bucket_done ;
3406
3407
};
3407
3408
3408
3409
static int bpf_iter_udp_realloc_batch (struct bpf_udp_iter_state * iter ,
3409
3410
unsigned int new_batch_sz , int flags );
3411
+ static struct sock * bpf_iter_udp_resume (struct sock * first_sk ,
3412
+ union bpf_udp_iter_batch_item * cookies ,
3413
+ int n_cookies )
3414
+ {
3415
+ struct sock * sk = NULL ;
3416
+ int i = 0 ;
3417
+
3418
+ for (; i < n_cookies ; i ++ ) {
3419
+ sk = first_sk ;
3420
+ udp_portaddr_for_each_entry_from (sk )
3421
+ if (cookies [i ].cookie == atomic64_read (& sk -> sk_cookie ))
3422
+ goto done ;
3423
+ }
3424
+ done :
3425
+ return sk ;
3426
+ }
3427
+
3410
3428
static struct sock * bpf_iter_udp_batch (struct seq_file * seq )
3411
3429
{
3412
3430
struct bpf_udp_iter_state * iter = seq -> private ;
3413
3431
struct udp_iter_state * state = & iter -> state ;
3432
+ unsigned int find_cookie , end_cookie = 0 ;
3414
3433
struct net * net = seq_file_net (seq );
3415
- int resume_bucket , resume_offset ;
3416
3434
struct udp_table * udptable ;
3417
3435
unsigned int batch_sks = 0 ;
3436
+ int resume_bucket ;
3418
3437
struct sock * sk ;
3419
3438
int resizes = 0 ;
3420
3439
int err = 0 ;
3421
3440
3422
3441
resume_bucket = state -> bucket ;
3423
- resume_offset = iter -> offset ;
3424
3442
3425
3443
/* The current batch is done, so advance the bucket. */
3426
3444
if (iter -> st_bucket_done )
@@ -3436,6 +3454,8 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
3436
3454
* before releasing the bucket lock. This allows BPF programs that are
3437
3455
* called in seq_show to acquire the bucket lock if needed.
3438
3456
*/
3457
+ find_cookie = iter -> cur_sk ;
3458
+ end_cookie = iter -> end_sk ;
3439
3459
iter -> cur_sk = 0 ;
3440
3460
iter -> end_sk = 0 ;
3441
3461
iter -> st_bucket_done = false;
@@ -3447,21 +3467,26 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
3447
3467
if (hlist_empty (& hslot2 -> head ))
3448
3468
goto next_bucket ;
3449
3469
3450
- iter -> offset = 0 ;
3451
3470
spin_lock_bh (& hslot2 -> lock );
3452
3471
sk = hlist_entry_safe (hslot2 -> head .first , struct sock ,
3453
3472
__sk_common .skc_portaddr_node );
3473
+ /* Resume from the first (in iteration order) unseen socket from
3474
+ * the last batch that still exists in resume_bucket. Most of
3475
+ * the time this will just be where the last iteration left off
3476
+ * in resume_bucket unless that socket disappeared between
3477
+ * reads.
3478
+ *
3479
+ * Skip this if end_cookie isn't set; this is the first
3480
+ * batch, we're on bucket zero, and we want to start from the
3481
+ * beginning.
3482
+ */
3483
+ if (state -> bucket == resume_bucket && end_cookie )
3484
+ sk = bpf_iter_udp_resume (sk ,
3485
+ & iter -> batch [find_cookie ],
3486
+ end_cookie - find_cookie );
3454
3487
fill_batch :
3455
3488
udp_portaddr_for_each_entry_from (sk ) {
3456
3489
if (seq_sk_match (seq , sk )) {
3457
- /* Resume from the last iterated socket at the
3458
- * offset in the bucket before iterator was stopped.
3459
- */
3460
- if (state -> bucket == resume_bucket &&
3461
- iter -> offset < resume_offset ) {
3462
- ++ iter -> offset ;
3463
- continue ;
3464
- }
3465
3490
if (iter -> end_sk < iter -> max_sk ) {
3466
3491
sock_hold (sk );
3467
3492
iter -> batch [iter -> end_sk ++ ].sock = sk ;
@@ -3530,10 +3555,8 @@ static void *bpf_iter_udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3530
3555
/* Whenever seq_next() is called, the iter->cur_sk is
3531
3556
* done with seq_show(), so unref the iter->cur_sk.
3532
3557
*/
3533
- if (iter -> cur_sk < iter -> end_sk ) {
3558
+ if (iter -> cur_sk < iter -> end_sk )
3534
3559
sock_put (iter -> batch [iter -> cur_sk ++ ].sock );
3535
- ++ iter -> offset ;
3536
- }
3537
3560
3538
3561
/* After updating iter->cur_sk, check if there are more sockets
3539
3562
* available in the current bucket batch.
@@ -3603,8 +3626,19 @@ static int bpf_iter_udp_seq_show(struct seq_file *seq, void *v)
3603
3626
3604
3627
static void bpf_iter_udp_put_batch (struct bpf_udp_iter_state * iter )
3605
3628
{
3606
- while (iter -> cur_sk < iter -> end_sk )
3607
- sock_put (iter -> batch [iter -> cur_sk ++ ].sock );
3629
+ union bpf_udp_iter_batch_item * item ;
3630
+ unsigned int cur_sk = iter -> cur_sk ;
3631
+ __u64 cookie ;
3632
+
3633
+ /* Remember the cookies of the sockets we haven't seen yet, so we can
3634
+ * pick up where we left off next time around.
3635
+ */
3636
+ while (cur_sk < iter -> end_sk ) {
3637
+ item = & iter -> batch [cur_sk ++ ];
3638
+ cookie = sock_gen_cookie (item -> sock );
3639
+ sock_put (item -> sock );
3640
+ item -> cookie = cookie ;
3641
+ }
3608
3642
}
3609
3643
3610
3644
static void bpf_iter_udp_seq_stop (struct seq_file * seq , void * v )
0 commit comments