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>
@@ -3392,33 +3393,50 @@ struct bpf_iter__udp {
3392
3393
3393
3394
union bpf_udp_iter_batch_item {
3394
3395
struct sock * sk ;
3396
+ __u64 cookie ;
3395
3397
};
3396
3398
3397
3399
struct bpf_udp_iter_state {
3398
3400
struct udp_iter_state state ;
3399
3401
unsigned int cur_sk ;
3400
3402
unsigned int end_sk ;
3401
3403
unsigned int max_sk ;
3402
- int offset ;
3403
3404
union bpf_udp_iter_batch_item * batch ;
3404
3405
};
3405
3406
3406
3407
static int bpf_iter_udp_realloc_batch (struct bpf_udp_iter_state * iter ,
3407
3408
unsigned int new_batch_sz , int flags );
3409
+ static struct sock * bpf_iter_udp_resume (struct sock * first_sk ,
3410
+ union bpf_udp_iter_batch_item * cookies ,
3411
+ int n_cookies )
3412
+ {
3413
+ struct sock * sk = NULL ;
3414
+ int i = 0 ;
3415
+
3416
+ for (; i < n_cookies ; i ++ ) {
3417
+ sk = first_sk ;
3418
+ udp_portaddr_for_each_entry_from (sk )
3419
+ if (cookies [i ].cookie == atomic64_read (& sk -> sk_cookie ))
3420
+ goto done ;
3421
+ }
3422
+ done :
3423
+ return sk ;
3424
+ }
3425
+
3408
3426
static struct sock * bpf_iter_udp_batch (struct seq_file * seq )
3409
3427
{
3410
3428
struct bpf_udp_iter_state * iter = seq -> private ;
3411
3429
struct udp_iter_state * state = & iter -> state ;
3430
+ unsigned int find_cookie , end_cookie = 0 ;
3412
3431
struct net * net = seq_file_net (seq );
3413
- int resume_bucket , resume_offset ;
3414
3432
struct udp_table * udptable ;
3415
3433
unsigned int batch_sks = 0 ;
3434
+ int resume_bucket ;
3416
3435
int resizes = 0 ;
3417
3436
struct sock * sk ;
3418
3437
int err = 0 ;
3419
3438
3420
3439
resume_bucket = state -> bucket ;
3421
- resume_offset = iter -> offset ;
3422
3440
3423
3441
/* The current batch is done, so advance the bucket. */
3424
3442
if (iter -> cur_sk == iter -> end_sk )
@@ -3434,6 +3452,8 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
3434
3452
* before releasing the bucket lock. This allows BPF programs that are
3435
3453
* called in seq_show to acquire the bucket lock if needed.
3436
3454
*/
3455
+ find_cookie = iter -> cur_sk ;
3456
+ end_cookie = iter -> end_sk ;
3437
3457
iter -> cur_sk = 0 ;
3438
3458
iter -> end_sk = 0 ;
3439
3459
batch_sks = 0 ;
@@ -3444,21 +3464,21 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
3444
3464
if (hlist_empty (& hslot2 -> head ))
3445
3465
goto next_bucket ;
3446
3466
3447
- iter -> offset = 0 ;
3448
3467
spin_lock_bh (& hslot2 -> lock );
3449
3468
sk = hlist_entry_safe (hslot2 -> head .first , struct sock ,
3450
3469
__sk_common .skc_portaddr_node );
3470
+ /* Resume from the first (in iteration order) unseen socket from
3471
+ * the last batch that still exists in resume_bucket. Most of
3472
+ * the time this will just be where the last iteration left off
3473
+ * in resume_bucket unless that socket disappeared between
3474
+ * reads.
3475
+ */
3476
+ if (state -> bucket == resume_bucket )
3477
+ sk = bpf_iter_udp_resume (sk , & iter -> batch [find_cookie ],
3478
+ end_cookie - find_cookie );
3451
3479
fill_batch :
3452
3480
udp_portaddr_for_each_entry_from (sk ) {
3453
3481
if (seq_sk_match (seq , sk )) {
3454
- /* Resume from the last iterated socket at the
3455
- * offset in the bucket before iterator was stopped.
3456
- */
3457
- if (state -> bucket == resume_bucket &&
3458
- iter -> offset < resume_offset ) {
3459
- ++ iter -> offset ;
3460
- continue ;
3461
- }
3462
3482
if (iter -> end_sk < iter -> max_sk ) {
3463
3483
sock_hold (sk );
3464
3484
iter -> batch [iter -> end_sk ++ ].sk = sk ;
@@ -3525,10 +3545,8 @@ static void *bpf_iter_udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3525
3545
/* Whenever seq_next() is called, the iter->cur_sk is
3526
3546
* done with seq_show(), so unref the iter->cur_sk.
3527
3547
*/
3528
- if (iter -> cur_sk < iter -> end_sk ) {
3548
+ if (iter -> cur_sk < iter -> end_sk )
3529
3549
sock_put (iter -> batch [iter -> cur_sk ++ ].sk );
3530
- ++ iter -> offset ;
3531
- }
3532
3550
3533
3551
/* After updating iter->cur_sk, check if there are more sockets
3534
3552
* available in the current bucket batch.
@@ -3598,10 +3616,19 @@ static int bpf_iter_udp_seq_show(struct seq_file *seq, void *v)
3598
3616
3599
3617
static void bpf_iter_udp_put_batch (struct bpf_udp_iter_state * iter )
3600
3618
{
3619
+ union bpf_udp_iter_batch_item * item ;
3601
3620
unsigned int cur_sk = iter -> cur_sk ;
3621
+ __u64 cookie ;
3602
3622
3603
- while (iter -> cur_sk < iter -> end_sk )
3604
- sock_put (iter -> batch [cur_sk ++ ].sk );
3623
+ /* Remember the cookies of the sockets we haven't seen yet, so we can
3624
+ * pick up where we left off next time around.
3625
+ */
3626
+ while (cur_sk < iter -> end_sk ) {
3627
+ item = & iter -> batch [cur_sk ++ ];
3628
+ cookie = sock_gen_cookie (item -> sk );
3629
+ sock_put (item -> sk );
3630
+ item -> cookie = cookie ;
3631
+ }
3605
3632
}
3606
3633
3607
3634
static void bpf_iter_udp_seq_stop (struct seq_file * seq , void * v )
0 commit comments