Skip to content

Commit cc1bb84

Browse files
Florian Westphalklassert
authored andcommitted
xfrm: policy: return NULL when inexact search needed
currently policy_hash_bysel() returns the hash bucket list (for exact policies), or the inexact list (when policy uses a prefix). Searching this inexact list is slow, so it might be better to pre-sort inexact lists into a tree or another data structure for faster searching. However, due to 'any' policies, that need to be searched in any case, doing so will require that 'inexact' policies need to be handled specially to decide the best search strategy. So change hash_bysel() and return NULL if the policy can't be handled via the policy hash table. Right now, we simply use the inexact list when this happens, but future patch can then implement a different strategy. Signed-off-by: Florian Westphal <[email protected]> Acked-by: David S. Miller <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent a927d6a commit cc1bb84

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

net/xfrm/xfrm_policy.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static struct hlist_head *policy_hash_bysel(struct net *net,
365365
hash = __sel_hash(sel, family, hmask, dbits, sbits);
366366

367367
if (hash == hmask + 1)
368-
return &net->xfrm.policy_inexact[dir];
368+
return NULL;
369369

370370
return rcu_dereference_check(net->xfrm.policy_bydst[dir].table,
371371
lockdep_is_held(&net->xfrm.xfrm_policy_lock)) + hash;
@@ -625,6 +625,8 @@ static void xfrm_hash_rebuild(struct work_struct *work)
625625
chain = policy_hash_bysel(net, &policy->selector,
626626
policy->family,
627627
xfrm_policy_id2dir(policy->index));
628+
if (!chain)
629+
chain = &net->xfrm.policy_inexact[dir];
628630
hlist_for_each_entry(pol, chain, bydst) {
629631
if (policy->priority >= pol->priority)
630632
newpos = &pol->bydst;
@@ -781,7 +783,12 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
781783

782784
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
783785
chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
784-
delpol = xfrm_policy_insert_list(chain, policy, excl);
786+
if (chain) {
787+
delpol = xfrm_policy_insert_list(chain, policy, excl);
788+
} else {
789+
chain = &net->xfrm.policy_inexact[dir];
790+
delpol = xfrm_policy_insert_list(chain, policy, excl);
791+
}
785792

786793
if (IS_ERR(delpol)) {
787794
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
@@ -829,6 +836,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
829836
*err = 0;
830837
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
831838
chain = policy_hash_bysel(net, sel, sel->family, dir);
839+
if (!chain)
840+
chain = &net->xfrm.policy_inexact[dir];
832841
ret = NULL;
833842
hlist_for_each_entry(pol, chain, bydst) {
834843
if (pol->type == type &&

0 commit comments

Comments
 (0)