@@ -201,6 +201,8 @@ xfrm_policy_inexact_lookup_rcu(struct net *net,
201
201
static struct xfrm_policy *
202
202
xfrm_policy_insert_list (struct hlist_head * chain , struct xfrm_policy * policy ,
203
203
bool excl );
204
+ static void xfrm_policy_insert_inexact_list (struct hlist_head * chain ,
205
+ struct xfrm_policy * policy );
204
206
205
207
static bool
206
208
xfrm_policy_find_inexact_candidates (struct xfrm_pol_inexact_candidates * cand ,
@@ -413,6 +415,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
413
415
if (policy ) {
414
416
write_pnet (& policy -> xp_net , net );
415
417
INIT_LIST_HEAD (& policy -> walk .all );
418
+ INIT_HLIST_NODE (& policy -> bydst_inexact_list );
416
419
INIT_HLIST_NODE (& policy -> bydst );
417
420
INIT_HLIST_NODE (& policy -> byidx );
418
421
rwlock_init (& policy -> lock );
@@ -1230,6 +1233,9 @@ xfrm_policy_inexact_insert(struct xfrm_policy *policy, u8 dir, int excl)
1230
1233
return ERR_PTR (- EEXIST );
1231
1234
}
1232
1235
1236
+ chain = & net -> xfrm .policy_inexact [dir ];
1237
+ xfrm_policy_insert_inexact_list (chain , policy );
1238
+
1233
1239
if (delpol )
1234
1240
__xfrm_policy_inexact_prune_bin (bin , false);
1235
1241
@@ -1337,6 +1343,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
1337
1343
continue ;
1338
1344
1339
1345
hlist_del_rcu (& policy -> bydst );
1346
+ hlist_del_init (& policy -> bydst_inexact_list );
1340
1347
1341
1348
newpos = NULL ;
1342
1349
dir = xfrm_policy_id2dir (policy -> index );
@@ -1506,6 +1513,36 @@ static const struct rhashtable_params xfrm_pol_inexact_params = {
1506
1513
.automatic_shrinking = true,
1507
1514
};
1508
1515
1516
+ static void xfrm_policy_insert_inexact_list (struct hlist_head * chain ,
1517
+ struct xfrm_policy * policy )
1518
+ {
1519
+ struct xfrm_policy * pol , * delpol = NULL ;
1520
+ struct hlist_node * newpos = NULL ;
1521
+
1522
+ hlist_for_each_entry (pol , chain , bydst_inexact_list ) {
1523
+ if (pol -> type == policy -> type &&
1524
+ pol -> if_id == policy -> if_id &&
1525
+ !selector_cmp (& pol -> selector , & policy -> selector ) &&
1526
+ xfrm_policy_mark_match (& policy -> mark , pol ) &&
1527
+ xfrm_sec_ctx_match (pol -> security , policy -> security ) &&
1528
+ !WARN_ON (delpol )) {
1529
+ delpol = pol ;
1530
+ if (policy -> priority > pol -> priority )
1531
+ continue ;
1532
+ } else if (policy -> priority >= pol -> priority ) {
1533
+ newpos = & pol -> bydst_inexact_list ;
1534
+ continue ;
1535
+ }
1536
+ if (delpol )
1537
+ break ;
1538
+ }
1539
+
1540
+ if (newpos && policy -> xdo .type != XFRM_DEV_OFFLOAD_PACKET )
1541
+ hlist_add_behind_rcu (& policy -> bydst_inexact_list , newpos );
1542
+ else
1543
+ hlist_add_head_rcu (& policy -> bydst_inexact_list , chain );
1544
+ }
1545
+
1509
1546
static struct xfrm_policy * xfrm_policy_insert_list (struct hlist_head * chain ,
1510
1547
struct xfrm_policy * policy ,
1511
1548
bool excl )
@@ -2307,6 +2344,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
2307
2344
/* Socket policies are not hashed. */
2308
2345
if (!hlist_unhashed (& pol -> bydst )) {
2309
2346
hlist_del_rcu (& pol -> bydst );
2347
+ hlist_del_init (& pol -> bydst_inexact_list );
2310
2348
hlist_del (& pol -> byidx );
2311
2349
}
2312
2350
0 commit comments