@@ -5335,131 +5335,29 @@ struct rt6_nh {
5335
5335
struct fib6_info * fib6_info ;
5336
5336
struct fib6_config r_cfg ;
5337
5337
struct list_head list ;
5338
- int weight ;
5339
5338
};
5340
5339
5341
- static void ip6_route_mpath_info_cleanup (struct list_head * rt6_nh_list )
5340
+ static int ip6_route_info_append (struct list_head * rt6_nh_list ,
5341
+ struct fib6_info * rt ,
5342
+ struct fib6_config * r_cfg )
5342
5343
{
5343
- struct rt6_nh * nh , * nh_next ;
5344
+ struct rt6_nh * nh ;
5344
5345
5345
- list_for_each_entry_safe (nh , nh_next , rt6_nh_list , list ) {
5346
- struct fib6_info * rt = nh -> fib6_info ;
5347
-
5348
- if (rt ) {
5349
- free_percpu (rt -> fib6_nh -> nh_common .nhc_pcpu_rth_output );
5350
- free_percpu (rt -> fib6_nh -> rt6i_pcpu );
5351
- ip_fib_metrics_put (rt -> fib6_metrics );
5352
- kfree (rt );
5353
- }
5354
-
5355
- list_del (& nh -> list );
5356
- kfree (nh );
5346
+ list_for_each_entry (nh , rt6_nh_list , list ) {
5347
+ /* check if fib6_info already exists */
5348
+ if (rt6_duplicate_nexthop (nh -> fib6_info , rt ))
5349
+ return - EEXIST ;
5357
5350
}
5358
- }
5359
-
5360
- static int ip6_route_mpath_info_create (struct list_head * rt6_nh_list ,
5361
- struct fib6_config * cfg ,
5362
- struct netlink_ext_ack * extack )
5363
- {
5364
- struct rtnexthop * rtnh ;
5365
- int remaining ;
5366
- int err ;
5367
-
5368
- remaining = cfg -> fc_mp_len ;
5369
- rtnh = (struct rtnexthop * )cfg -> fc_mp ;
5370
-
5371
- /* Parse a Multipath Entry and build a list (rt6_nh_list) of
5372
- * fib6_info structs per nexthop
5373
- */
5374
- while (rtnh_ok (rtnh , remaining )) {
5375
- struct fib6_config r_cfg ;
5376
- struct fib6_info * rt ;
5377
- struct rt6_nh * nh ;
5378
- int attrlen ;
5379
-
5380
- nh = kzalloc (sizeof (* nh ), GFP_KERNEL );
5381
- if (!nh ) {
5382
- err = - ENOMEM ;
5383
- goto err ;
5384
- }
5385
5351
5386
- list_add_tail (& nh -> list , rt6_nh_list );
5387
-
5388
- memcpy (& r_cfg , cfg , sizeof (* cfg ));
5389
- if (rtnh -> rtnh_ifindex )
5390
- r_cfg .fc_ifindex = rtnh -> rtnh_ifindex ;
5391
-
5392
- attrlen = rtnh_attrlen (rtnh );
5393
- if (attrlen > 0 ) {
5394
- struct nlattr * nla , * attrs = rtnh_attrs (rtnh );
5395
-
5396
- nla = nla_find (attrs , attrlen , RTA_GATEWAY );
5397
- if (nla ) {
5398
- r_cfg .fc_gateway = nla_get_in6_addr (nla );
5399
- r_cfg .fc_flags |= RTF_GATEWAY ;
5400
- }
5401
-
5402
- r_cfg .fc_encap = nla_find (attrs , attrlen , RTA_ENCAP );
5403
- nla = nla_find (attrs , attrlen , RTA_ENCAP_TYPE );
5404
- if (nla )
5405
- r_cfg .fc_encap_type = nla_get_u16 (nla );
5406
- }
5407
-
5408
- r_cfg .fc_flags |= (rtnh -> rtnh_flags & RTNH_F_ONLINK );
5409
-
5410
- rt = ip6_route_info_create (& r_cfg , GFP_KERNEL , extack );
5411
- if (IS_ERR (rt )) {
5412
- err = PTR_ERR (rt );
5413
- goto err ;
5414
- }
5415
-
5416
- nh -> fib6_info = rt ;
5417
- nh -> weight = rtnh -> rtnh_hops + 1 ;
5418
- memcpy (& nh -> r_cfg , & r_cfg , sizeof (r_cfg ));
5352
+ nh = kzalloc (sizeof (* nh ), GFP_KERNEL );
5353
+ if (!nh )
5354
+ return - ENOMEM ;
5419
5355
5420
- rtnh = rtnh_next (rtnh , & remaining );
5421
- }
5356
+ nh -> fib6_info = rt ;
5357
+ memcpy (& nh -> r_cfg , r_cfg , sizeof (* r_cfg ));
5358
+ list_add_tail (& nh -> list , rt6_nh_list );
5422
5359
5423
5360
return 0 ;
5424
- err :
5425
- ip6_route_mpath_info_cleanup (rt6_nh_list );
5426
- return err ;
5427
- }
5428
-
5429
- static int ip6_route_mpath_info_create_nh (struct list_head * rt6_nh_list ,
5430
- struct netlink_ext_ack * extack )
5431
- {
5432
- struct rt6_nh * nh , * nh_next , * nh_tmp ;
5433
- LIST_HEAD (tmp );
5434
- int err ;
5435
-
5436
- list_for_each_entry_safe (nh , nh_next , rt6_nh_list , list ) {
5437
- struct fib6_info * rt = nh -> fib6_info ;
5438
-
5439
- err = ip6_route_info_create_nh (rt , & nh -> r_cfg , extack );
5440
- if (err ) {
5441
- nh -> fib6_info = NULL ;
5442
- goto err ;
5443
- }
5444
-
5445
- rt -> fib6_nh -> fib_nh_weight = nh -> weight ;
5446
-
5447
- list_move_tail (& nh -> list , & tmp );
5448
-
5449
- list_for_each_entry (nh_tmp , rt6_nh_list , list ) {
5450
- /* check if fib6_info already exists */
5451
- if (rt6_duplicate_nexthop (nh_tmp -> fib6_info , rt )) {
5452
- err = - EEXIST ;
5453
- goto err ;
5454
- }
5455
- }
5456
- }
5457
- out :
5458
- list_splice (& tmp , rt6_nh_list );
5459
- return err ;
5460
- err :
5461
- ip6_route_mpath_info_cleanup (rt6_nh_list );
5462
- goto out ;
5463
5361
}
5464
5362
5465
5363
static void ip6_route_mpath_notify (struct fib6_info * rt ,
@@ -5519,11 +5417,16 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
5519
5417
struct fib6_info * rt_notif = NULL , * rt_last = NULL ;
5520
5418
struct nl_info * info = & cfg -> fc_nlinfo ;
5521
5419
struct rt6_nh * nh , * nh_safe ;
5420
+ struct fib6_config r_cfg ;
5421
+ struct rtnexthop * rtnh ;
5522
5422
LIST_HEAD (rt6_nh_list );
5523
5423
struct rt6_nh * err_nh ;
5424
+ struct fib6_info * rt ;
5524
5425
__u16 nlflags ;
5525
- int nhn = 0 ;
5426
+ int remaining ;
5427
+ int attrlen ;
5526
5428
int replace ;
5429
+ int nhn = 0 ;
5527
5430
int err ;
5528
5431
5529
5432
replace = (cfg -> fc_nlinfo .nlh &&
@@ -5533,13 +5436,57 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
5533
5436
if (info -> nlh && info -> nlh -> nlmsg_flags & NLM_F_APPEND )
5534
5437
nlflags |= NLM_F_APPEND ;
5535
5438
5536
- err = ip6_route_mpath_info_create (& rt6_nh_list , cfg , extack );
5537
- if (err )
5538
- return err ;
5439
+ remaining = cfg -> fc_mp_len ;
5440
+ rtnh = (struct rtnexthop * )cfg -> fc_mp ;
5539
5441
5540
- err = ip6_route_mpath_info_create_nh (& rt6_nh_list , extack );
5541
- if (err )
5542
- goto cleanup ;
5442
+ /* Parse a Multipath Entry and build a list (rt6_nh_list) of
5443
+ * fib6_info structs per nexthop
5444
+ */
5445
+ while (rtnh_ok (rtnh , remaining )) {
5446
+ memcpy (& r_cfg , cfg , sizeof (* cfg ));
5447
+ if (rtnh -> rtnh_ifindex )
5448
+ r_cfg .fc_ifindex = rtnh -> rtnh_ifindex ;
5449
+
5450
+ attrlen = rtnh_attrlen (rtnh );
5451
+ if (attrlen > 0 ) {
5452
+ struct nlattr * nla , * attrs = rtnh_attrs (rtnh );
5453
+
5454
+ nla = nla_find (attrs , attrlen , RTA_GATEWAY );
5455
+ if (nla ) {
5456
+ r_cfg .fc_gateway = nla_get_in6_addr (nla );
5457
+ r_cfg .fc_flags |= RTF_GATEWAY ;
5458
+ }
5459
+
5460
+ r_cfg .fc_encap = nla_find (attrs , attrlen , RTA_ENCAP );
5461
+ nla = nla_find (attrs , attrlen , RTA_ENCAP_TYPE );
5462
+ if (nla )
5463
+ r_cfg .fc_encap_type = nla_get_u16 (nla );
5464
+ }
5465
+
5466
+ r_cfg .fc_flags |= (rtnh -> rtnh_flags & RTNH_F_ONLINK );
5467
+ rt = ip6_route_info_create (& r_cfg , GFP_KERNEL , extack );
5468
+ if (IS_ERR (rt )) {
5469
+ err = PTR_ERR (rt );
5470
+ rt = NULL ;
5471
+ goto cleanup ;
5472
+ }
5473
+
5474
+ err = ip6_route_info_create_nh (rt , & r_cfg , extack );
5475
+ if (err ) {
5476
+ rt = NULL ;
5477
+ goto cleanup ;
5478
+ }
5479
+
5480
+ rt -> fib6_nh -> fib_nh_weight = rtnh -> rtnh_hops + 1 ;
5481
+
5482
+ err = ip6_route_info_append (& rt6_nh_list , rt , & r_cfg );
5483
+ if (err ) {
5484
+ fib6_info_release (rt );
5485
+ goto cleanup ;
5486
+ }
5487
+
5488
+ rtnh = rtnh_next (rtnh , & remaining );
5489
+ }
5543
5490
5544
5491
/* for add and replace send one notification with all nexthops.
5545
5492
* Skip the notification in fib6_add_rt2node and send one with
0 commit comments