@@ -388,6 +388,88 @@ static const struct file_operations nsim_dev_rate_parent_fops = {
388
388
.owner = THIS_MODULE ,
389
389
};
390
390
391
+ static ssize_t nsim_dev_peer_read (struct file * file , char __user * data ,
392
+ size_t count , loff_t * ppos )
393
+ {
394
+ struct nsim_dev_port * nsim_dev_port ;
395
+ struct netdevsim * peer ;
396
+ unsigned int id , port ;
397
+ char buf [23 ];
398
+ ssize_t len ;
399
+
400
+ nsim_dev_port = file -> private_data ;
401
+ rcu_read_lock ();
402
+ peer = rcu_dereference (nsim_dev_port -> ns -> peer );
403
+ if (!peer ) {
404
+ len = scnprintf (buf , sizeof (buf ), "\n" );
405
+ goto out ;
406
+ }
407
+
408
+ id = peer -> nsim_bus_dev -> dev .id ;
409
+ port = peer -> nsim_dev_port -> port_index ;
410
+ len = scnprintf (buf , sizeof (buf ), "%u %u\n" , id , port );
411
+
412
+ out :
413
+ rcu_read_unlock ();
414
+ return simple_read_from_buffer (data , count , ppos , buf , len );
415
+ }
416
+
417
+ static ssize_t nsim_dev_peer_write (struct file * file ,
418
+ const char __user * data ,
419
+ size_t count , loff_t * ppos )
420
+ {
421
+ struct nsim_dev_port * nsim_dev_port , * peer_dev_port ;
422
+ struct nsim_bus_dev * peer_bus_dev ;
423
+ struct nsim_dev * peer_dev ;
424
+ unsigned int id , port ;
425
+ char buf [22 ];
426
+ ssize_t ret ;
427
+
428
+ if (count >= sizeof (buf ))
429
+ return - ENOSPC ;
430
+
431
+ ret = copy_from_user (buf , data , count );
432
+ if (ret )
433
+ return - EFAULT ;
434
+ buf [count ] = '\0' ;
435
+
436
+ ret = sscanf (buf , "%u %u" , & id , & port );
437
+ if (ret != 2 ) {
438
+ pr_err ("Format for adding a peer is \"id port\" (uint uint)" );
439
+ return - EINVAL ;
440
+ }
441
+
442
+ /* invalid netdevsim id */
443
+ peer_bus_dev = nsim_bus_dev_get (id );
444
+ if (!peer_bus_dev )
445
+ return - EINVAL ;
446
+
447
+ /* cannot link to self */
448
+ nsim_dev_port = file -> private_data ;
449
+ if (nsim_dev_port -> ns -> nsim_bus_dev == peer_bus_dev &&
450
+ nsim_dev_port -> port_index == port )
451
+ return - EINVAL ;
452
+
453
+ peer_dev = dev_get_drvdata (& peer_bus_dev -> dev );
454
+ list_for_each_entry (peer_dev_port , & peer_dev -> port_list , list ) {
455
+ if (peer_dev_port -> port_index != port )
456
+ continue ;
457
+ rcu_assign_pointer (nsim_dev_port -> ns -> peer , peer_dev_port -> ns );
458
+ rcu_assign_pointer (peer_dev_port -> ns -> peer , nsim_dev_port -> ns );
459
+ return count ;
460
+ }
461
+
462
+ return - EINVAL ;
463
+ }
464
+
465
+ static const struct file_operations nsim_dev_peer_fops = {
466
+ .open = simple_open ,
467
+ .read = nsim_dev_peer_read ,
468
+ .write = nsim_dev_peer_write ,
469
+ .llseek = generic_file_llseek ,
470
+ .owner = THIS_MODULE ,
471
+ };
472
+
391
473
static int nsim_dev_port_debugfs_init (struct nsim_dev * nsim_dev ,
392
474
struct nsim_dev_port * nsim_dev_port )
393
475
{
@@ -418,6 +500,9 @@ static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
418
500
}
419
501
debugfs_create_symlink ("dev" , nsim_dev_port -> ddir , dev_link_name );
420
502
503
+ debugfs_create_file ("peer" , 0600 , nsim_dev_port -> ddir ,
504
+ nsim_dev_port , & nsim_dev_peer_fops );
505
+
421
506
return 0 ;
422
507
}
423
508
0 commit comments