@@ -6408,6 +6408,9 @@ struct netdev_adjacent {
6408
6408
/* upper master flag, there can only be one master device per list */
6409
6409
bool master ;
6410
6410
6411
+ /* lookup ignore flag */
6412
+ bool ignore ;
6413
+
6411
6414
/* counter for the number of times this device was added to us */
6412
6415
u16 ref_nr ;
6413
6416
@@ -6430,7 +6433,7 @@ static struct netdev_adjacent *__netdev_find_adj(struct net_device *adj_dev,
6430
6433
return NULL ;
6431
6434
}
6432
6435
6433
- static int __netdev_has_upper_dev (struct net_device * upper_dev , void * data )
6436
+ static int ____netdev_has_upper_dev (struct net_device * upper_dev , void * data )
6434
6437
{
6435
6438
struct net_device * dev = data ;
6436
6439
@@ -6451,7 +6454,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
6451
6454
{
6452
6455
ASSERT_RTNL ();
6453
6456
6454
- return netdev_walk_all_upper_dev_rcu (dev , __netdev_has_upper_dev ,
6457
+ return netdev_walk_all_upper_dev_rcu (dev , ____netdev_has_upper_dev ,
6455
6458
upper_dev );
6456
6459
}
6457
6460
EXPORT_SYMBOL (netdev_has_upper_dev );
@@ -6469,7 +6472,7 @@ EXPORT_SYMBOL(netdev_has_upper_dev);
6469
6472
bool netdev_has_upper_dev_all_rcu (struct net_device * dev ,
6470
6473
struct net_device * upper_dev )
6471
6474
{
6472
- return !!netdev_walk_all_upper_dev_rcu (dev , __netdev_has_upper_dev ,
6475
+ return !!netdev_walk_all_upper_dev_rcu (dev , ____netdev_has_upper_dev ,
6473
6476
upper_dev );
6474
6477
}
6475
6478
EXPORT_SYMBOL (netdev_has_upper_dev_all_rcu );
@@ -6513,6 +6516,22 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
6513
6516
}
6514
6517
EXPORT_SYMBOL (netdev_master_upper_dev_get );
6515
6518
6519
+ static struct net_device * __netdev_master_upper_dev_get (struct net_device * dev )
6520
+ {
6521
+ struct netdev_adjacent * upper ;
6522
+
6523
+ ASSERT_RTNL ();
6524
+
6525
+ if (list_empty (& dev -> adj_list .upper ))
6526
+ return NULL ;
6527
+
6528
+ upper = list_first_entry (& dev -> adj_list .upper ,
6529
+ struct netdev_adjacent , list );
6530
+ if (likely (upper -> master ) && !upper -> ignore )
6531
+ return upper -> dev ;
6532
+ return NULL ;
6533
+ }
6534
+
6516
6535
/**
6517
6536
* netdev_has_any_lower_dev - Check if device is linked to some device
6518
6537
* @dev: device
@@ -6563,8 +6582,9 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
6563
6582
}
6564
6583
EXPORT_SYMBOL (netdev_upper_get_next_dev_rcu );
6565
6584
6566
- static struct net_device * netdev_next_upper_dev (struct net_device * dev ,
6567
- struct list_head * * iter )
6585
+ static struct net_device * __netdev_next_upper_dev (struct net_device * dev ,
6586
+ struct list_head * * iter ,
6587
+ bool * ignore )
6568
6588
{
6569
6589
struct netdev_adjacent * upper ;
6570
6590
@@ -6574,6 +6594,7 @@ static struct net_device *netdev_next_upper_dev(struct net_device *dev,
6574
6594
return NULL ;
6575
6595
6576
6596
* iter = & upper -> list ;
6597
+ * ignore = upper -> ignore ;
6577
6598
6578
6599
return upper -> dev ;
6579
6600
}
@@ -6595,14 +6616,15 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
6595
6616
return upper -> dev ;
6596
6617
}
6597
6618
6598
- static int netdev_walk_all_upper_dev (struct net_device * dev ,
6599
- int (* fn )(struct net_device * dev ,
6600
- void * data ),
6601
- void * data )
6619
+ static int __netdev_walk_all_upper_dev (struct net_device * dev ,
6620
+ int (* fn )(struct net_device * dev ,
6621
+ void * data ),
6622
+ void * data )
6602
6623
{
6603
6624
struct net_device * udev , * next , * now , * dev_stack [MAX_NEST_DEV + 1 ];
6604
6625
struct list_head * niter , * iter , * iter_stack [MAX_NEST_DEV + 1 ];
6605
6626
int ret , cur = 0 ;
6627
+ bool ignore ;
6606
6628
6607
6629
now = dev ;
6608
6630
iter = & dev -> adj_list .upper ;
@@ -6616,9 +6638,11 @@ static int netdev_walk_all_upper_dev(struct net_device *dev,
6616
6638
6617
6639
next = NULL ;
6618
6640
while (1 ) {
6619
- udev = netdev_next_upper_dev (now , & iter );
6641
+ udev = __netdev_next_upper_dev (now , & iter , & ignore );
6620
6642
if (!udev )
6621
6643
break ;
6644
+ if (ignore )
6645
+ continue ;
6622
6646
6623
6647
next = udev ;
6624
6648
niter = & udev -> adj_list .upper ;
@@ -6688,6 +6712,15 @@ int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
6688
6712
}
6689
6713
EXPORT_SYMBOL_GPL (netdev_walk_all_upper_dev_rcu );
6690
6714
6715
+ static bool __netdev_has_upper_dev (struct net_device * dev ,
6716
+ struct net_device * upper_dev )
6717
+ {
6718
+ ASSERT_RTNL ();
6719
+
6720
+ return __netdev_walk_all_upper_dev (dev , ____netdev_has_upper_dev ,
6721
+ upper_dev );
6722
+ }
6723
+
6691
6724
/**
6692
6725
* netdev_lower_get_next_private - Get the next ->private from the
6693
6726
* lower neighbour list
@@ -6784,6 +6817,23 @@ static struct net_device *netdev_next_lower_dev(struct net_device *dev,
6784
6817
return lower -> dev ;
6785
6818
}
6786
6819
6820
+ static struct net_device * __netdev_next_lower_dev (struct net_device * dev ,
6821
+ struct list_head * * iter ,
6822
+ bool * ignore )
6823
+ {
6824
+ struct netdev_adjacent * lower ;
6825
+
6826
+ lower = list_entry ((* iter )-> next , struct netdev_adjacent , list );
6827
+
6828
+ if (& lower -> list == & dev -> adj_list .lower )
6829
+ return NULL ;
6830
+
6831
+ * iter = & lower -> list ;
6832
+ * ignore = lower -> ignore ;
6833
+
6834
+ return lower -> dev ;
6835
+ }
6836
+
6787
6837
int netdev_walk_all_lower_dev (struct net_device * dev ,
6788
6838
int (* fn )(struct net_device * dev ,
6789
6839
void * data ),
@@ -6831,6 +6881,55 @@ int netdev_walk_all_lower_dev(struct net_device *dev,
6831
6881
}
6832
6882
EXPORT_SYMBOL_GPL (netdev_walk_all_lower_dev );
6833
6883
6884
+ static int __netdev_walk_all_lower_dev (struct net_device * dev ,
6885
+ int (* fn )(struct net_device * dev ,
6886
+ void * data ),
6887
+ void * data )
6888
+ {
6889
+ struct net_device * ldev , * next , * now , * dev_stack [MAX_NEST_DEV + 1 ];
6890
+ struct list_head * niter , * iter , * iter_stack [MAX_NEST_DEV + 1 ];
6891
+ int ret , cur = 0 ;
6892
+ bool ignore ;
6893
+
6894
+ now = dev ;
6895
+ iter = & dev -> adj_list .lower ;
6896
+
6897
+ while (1 ) {
6898
+ if (now != dev ) {
6899
+ ret = fn (now , data );
6900
+ if (ret )
6901
+ return ret ;
6902
+ }
6903
+
6904
+ next = NULL ;
6905
+ while (1 ) {
6906
+ ldev = __netdev_next_lower_dev (now , & iter , & ignore );
6907
+ if (!ldev )
6908
+ break ;
6909
+ if (ignore )
6910
+ continue ;
6911
+
6912
+ next = ldev ;
6913
+ niter = & ldev -> adj_list .lower ;
6914
+ dev_stack [cur ] = now ;
6915
+ iter_stack [cur ++ ] = iter ;
6916
+ break ;
6917
+ }
6918
+
6919
+ if (!next ) {
6920
+ if (!cur )
6921
+ return 0 ;
6922
+ next = dev_stack [-- cur ];
6923
+ niter = iter_stack [cur ];
6924
+ }
6925
+
6926
+ now = next ;
6927
+ iter = niter ;
6928
+ }
6929
+
6930
+ return 0 ;
6931
+ }
6932
+
6834
6933
static struct net_device * netdev_next_lower_dev_rcu (struct net_device * dev ,
6835
6934
struct list_head * * iter )
6836
6935
{
@@ -6850,11 +6949,14 @@ static u8 __netdev_upper_depth(struct net_device *dev)
6850
6949
struct net_device * udev ;
6851
6950
struct list_head * iter ;
6852
6951
u8 max_depth = 0 ;
6952
+ bool ignore ;
6853
6953
6854
6954
for (iter = & dev -> adj_list .upper ,
6855
- udev = netdev_next_upper_dev (dev , & iter );
6955
+ udev = __netdev_next_upper_dev (dev , & iter , & ignore );
6856
6956
udev ;
6857
- udev = netdev_next_upper_dev (dev , & iter )) {
6957
+ udev = __netdev_next_upper_dev (dev , & iter , & ignore )) {
6958
+ if (ignore )
6959
+ continue ;
6858
6960
if (max_depth < udev -> upper_level )
6859
6961
max_depth = udev -> upper_level ;
6860
6962
}
@@ -6867,11 +6969,14 @@ static u8 __netdev_lower_depth(struct net_device *dev)
6867
6969
struct net_device * ldev ;
6868
6970
struct list_head * iter ;
6869
6971
u8 max_depth = 0 ;
6972
+ bool ignore ;
6870
6973
6871
6974
for (iter = & dev -> adj_list .lower ,
6872
- ldev = netdev_next_lower_dev (dev , & iter );
6975
+ ldev = __netdev_next_lower_dev (dev , & iter , & ignore );
6873
6976
ldev ;
6874
- ldev = netdev_next_lower_dev (dev , & iter )) {
6977
+ ldev = __netdev_next_lower_dev (dev , & iter , & ignore )) {
6978
+ if (ignore )
6979
+ continue ;
6875
6980
if (max_depth < ldev -> lower_level )
6876
6981
max_depth = ldev -> lower_level ;
6877
6982
}
@@ -7035,6 +7140,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
7035
7140
adj -> master = master ;
7036
7141
adj -> ref_nr = 1 ;
7037
7142
adj -> private = private ;
7143
+ adj -> ignore = false;
7038
7144
dev_hold (adj_dev );
7039
7145
7040
7146
pr_debug ("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n" ,
@@ -7185,17 +7291,17 @@ static int __netdev_upper_dev_link(struct net_device *dev,
7185
7291
return - EBUSY ;
7186
7292
7187
7293
/* To prevent loops, check if dev is not upper device to upper_dev. */
7188
- if (netdev_has_upper_dev (upper_dev , dev ))
7294
+ if (__netdev_has_upper_dev (upper_dev , dev ))
7189
7295
return - EBUSY ;
7190
7296
7191
7297
if ((dev -> lower_level + upper_dev -> upper_level ) > MAX_NEST_DEV )
7192
7298
return - EMLINK ;
7193
7299
7194
7300
if (!master ) {
7195
- if (netdev_has_upper_dev (dev , upper_dev ))
7301
+ if (__netdev_has_upper_dev (dev , upper_dev ))
7196
7302
return - EEXIST ;
7197
7303
} else {
7198
- master_dev = netdev_master_upper_dev_get (dev );
7304
+ master_dev = __netdev_master_upper_dev_get (dev );
7199
7305
if (master_dev )
7200
7306
return master_dev == upper_dev ? - EEXIST : - EBUSY ;
7201
7307
}
@@ -7218,10 +7324,11 @@ static int __netdev_upper_dev_link(struct net_device *dev,
7218
7324
goto rollback ;
7219
7325
7220
7326
__netdev_update_upper_level (dev , NULL );
7221
- netdev_walk_all_lower_dev (dev , __netdev_update_upper_level , NULL );
7327
+ __netdev_walk_all_lower_dev (dev , __netdev_update_upper_level , NULL );
7222
7328
7223
7329
__netdev_update_lower_level (upper_dev , NULL );
7224
- netdev_walk_all_upper_dev (upper_dev , __netdev_update_lower_level , NULL );
7330
+ __netdev_walk_all_upper_dev (upper_dev , __netdev_update_lower_level ,
7331
+ NULL );
7225
7332
7226
7333
return 0 ;
7227
7334
@@ -7307,13 +7414,94 @@ void netdev_upper_dev_unlink(struct net_device *dev,
7307
7414
& changeupper_info .info );
7308
7415
7309
7416
__netdev_update_upper_level (dev , NULL );
7310
- netdev_walk_all_lower_dev (dev , __netdev_update_upper_level , NULL );
7417
+ __netdev_walk_all_lower_dev (dev , __netdev_update_upper_level , NULL );
7311
7418
7312
7419
__netdev_update_lower_level (upper_dev , NULL );
7313
- netdev_walk_all_upper_dev (upper_dev , __netdev_update_lower_level , NULL );
7420
+ __netdev_walk_all_upper_dev (upper_dev , __netdev_update_lower_level ,
7421
+ NULL );
7314
7422
}
7315
7423
EXPORT_SYMBOL (netdev_upper_dev_unlink );
7316
7424
7425
+ static void __netdev_adjacent_dev_set (struct net_device * upper_dev ,
7426
+ struct net_device * lower_dev ,
7427
+ bool val )
7428
+ {
7429
+ struct netdev_adjacent * adj ;
7430
+
7431
+ adj = __netdev_find_adj (lower_dev , & upper_dev -> adj_list .lower );
7432
+ if (adj )
7433
+ adj -> ignore = val ;
7434
+
7435
+ adj = __netdev_find_adj (upper_dev , & lower_dev -> adj_list .upper );
7436
+ if (adj )
7437
+ adj -> ignore = val ;
7438
+ }
7439
+
7440
+ static void netdev_adjacent_dev_disable (struct net_device * upper_dev ,
7441
+ struct net_device * lower_dev )
7442
+ {
7443
+ __netdev_adjacent_dev_set (upper_dev , lower_dev , true);
7444
+ }
7445
+
7446
+ static void netdev_adjacent_dev_enable (struct net_device * upper_dev ,
7447
+ struct net_device * lower_dev )
7448
+ {
7449
+ __netdev_adjacent_dev_set (upper_dev , lower_dev , false);
7450
+ }
7451
+
7452
+ int netdev_adjacent_change_prepare (struct net_device * old_dev ,
7453
+ struct net_device * new_dev ,
7454
+ struct net_device * dev ,
7455
+ struct netlink_ext_ack * extack )
7456
+ {
7457
+ int err ;
7458
+
7459
+ if (!new_dev )
7460
+ return 0 ;
7461
+
7462
+ if (old_dev && new_dev != old_dev )
7463
+ netdev_adjacent_dev_disable (dev , old_dev );
7464
+
7465
+ err = netdev_upper_dev_link (new_dev , dev , extack );
7466
+ if (err ) {
7467
+ if (old_dev && new_dev != old_dev )
7468
+ netdev_adjacent_dev_enable (dev , old_dev );
7469
+ return err ;
7470
+ }
7471
+
7472
+ return 0 ;
7473
+ }
7474
+ EXPORT_SYMBOL (netdev_adjacent_change_prepare );
7475
+
7476
+ void netdev_adjacent_change_commit (struct net_device * old_dev ,
7477
+ struct net_device * new_dev ,
7478
+ struct net_device * dev )
7479
+ {
7480
+ if (!new_dev || !old_dev )
7481
+ return ;
7482
+
7483
+ if (new_dev == old_dev )
7484
+ return ;
7485
+
7486
+ netdev_adjacent_dev_enable (dev , old_dev );
7487
+ netdev_upper_dev_unlink (old_dev , dev );
7488
+ }
7489
+ EXPORT_SYMBOL (netdev_adjacent_change_commit );
7490
+
7491
+ void netdev_adjacent_change_abort (struct net_device * old_dev ,
7492
+ struct net_device * new_dev ,
7493
+ struct net_device * dev )
7494
+ {
7495
+ if (!new_dev )
7496
+ return ;
7497
+
7498
+ if (old_dev && new_dev != old_dev )
7499
+ netdev_adjacent_dev_enable (dev , old_dev );
7500
+
7501
+ netdev_upper_dev_unlink (new_dev , dev );
7502
+ }
7503
+ EXPORT_SYMBOL (netdev_adjacent_change_abort );
7504
+
7317
7505
/**
7318
7506
* netdev_bonding_info_change - Dispatch event about slave change
7319
7507
* @dev: device
0 commit comments