struct xfrm_pol_inexact_key {
possible_net_t net;
+ u32 if_id;
u16 family;
u8 dir, type;
};
int dir);
static struct xfrm_pol_inexact_bin *
-xfrm_policy_inexact_lookup(struct net *net, u8 type, u16 family, u8 dir);
+xfrm_policy_inexact_lookup(struct net *net, u8 type, u16 family, u8 dir,
+ u32 if_id);
static struct xfrm_pol_inexact_bin *
xfrm_policy_inexact_lookup_rcu(struct net *net,
- u8 type, u16 family, u8 dir);
+ u8 type, u16 family, u8 dir, u32 if_id);
static struct xfrm_policy *
xfrm_policy_insert_list(struct hlist_head *chain, struct xfrm_policy *policy,
bool excl);
.family = pol->family,
.type = pol->type,
.dir = dir,
+ .if_id = pol->if_id,
};
struct net *net = xp_net(pol);
const struct xfrm_pol_inexact_key *k = data;
u32 a = k->type << 24 | k->dir << 16 | k->family;
- return jhash_2words(a, net_hash_mix(read_pnet(&k->net)), seed);
+ return jhash_3words(a, k->if_id, net_hash_mix(read_pnet(&k->net)),
+ seed);
}
static u32 xfrm_pol_bin_obj(const void *data, u32 len, u32 seed)
if (ret)
return ret;
- return 0;
+ return b->k.if_id ^ key->if_id;
}
static const struct rhashtable_params xfrm_pol_inexact_params = {
chain = policy_hash_bysel(net, sel, sel->family, dir);
if (!chain) {
bin = xfrm_policy_inexact_lookup(net, type,
- sel->family, dir);
+ sel->family, dir, if_id);
if (!bin) {
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
return NULL;
}
static struct xfrm_pol_inexact_bin *
-xfrm_policy_inexact_lookup_rcu(struct net *net, u8 type, u16 family, u8 dir)
+xfrm_policy_inexact_lookup_rcu(struct net *net, u8 type, u16 family,
+ u8 dir, u32 if_id)
{
struct xfrm_pol_inexact_key k = {
.family = family,
.type = type,
.dir = dir,
+ .if_id = if_id,
};
write_pnet(&k.net, net);
}
static struct xfrm_pol_inexact_bin *
-xfrm_policy_inexact_lookup(struct net *net, u8 type, u16 family, u8 dir)
+xfrm_policy_inexact_lookup(struct net *net, u8 type, u16 family,
+ u8 dir, u32 if_id)
{
struct xfrm_pol_inexact_bin *bin;
lockdep_assert_held(&net->xfrm.xfrm_policy_lock);
rcu_read_lock();
- bin = xfrm_policy_inexact_lookup_rcu(net, type, family, dir);
+ bin = xfrm_policy_inexact_lookup_rcu(net, type, family, dir, if_id);
rcu_read_unlock();
return bin;
break;
}
}
- bin = xfrm_policy_inexact_lookup_rcu(net, type, family, dir);
+ bin = xfrm_policy_inexact_lookup_rcu(net, type, family, dir, if_id);
if (!bin)
goto skip_inexact;
chain = &bin->hhead;