Skip to content

Commit

Permalink
xfrm: Namespacify xfrm state/policy locks
Browse files Browse the repository at this point in the history
By semantics, xfrm layer is fully name space aware,
so will the locks, e.g. xfrm_state/pocliy_lock.
Ensure exclusive access into state/policy link list
for different name space with one global lock is not
right in terms of semantics aspect at first place,
as they are indeed mutually independent with each
other, but also more seriously causes scalability
problem.

One practical scenario is on a Open Network Stack,
more than hundreds of lxc tenants acts as routers
within one host, a global xfrm_state/policy_lock
becomes the bottleneck. But onces those locks are
decoupled in a per-namespace fashion, locks contend
is just with in specific name space scope, without
causing additional SPD/SAD access delay for other
name space.

Also this patch improve scalability while as without
changing original xfrm behavior.

Signed-off-by: Fan Du <[email protected]>
Signed-off-by: Steffen Klassert <[email protected]>
  • Loading branch information
Fan Du authored and klassert committed Dec 6, 2013
1 parent 8d549c4 commit 283bc9f
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 114 deletions.
4 changes: 4 additions & 0 deletions include/net/netns/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ struct netns_xfrm {
#if IS_ENABLED(CONFIG_IPV6)
struct dst_ops xfrm6_dst_ops;
#endif
spinlock_t xfrm_state_lock;
spinlock_t xfrm_policy_sk_bundle_lock;
rwlock_t xfrm_policy_lock;
struct mutex xfrm_cfg_mutex;
};

#endif
11 changes: 5 additions & 6 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
#define XFRM_INC_STATS_USER(net, field) ((void)(net))
#endif

extern struct mutex xfrm_cfg_mutex;

/* Organization of SPD aka "XFRM rules"
------------------------------------
Expand Down Expand Up @@ -1409,7 +1408,7 @@ static inline void xfrm_sysctl_fini(struct net *net)
void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
int (*func)(struct xfrm_state *, int, void*), void *);
void xfrm_state_walk_done(struct xfrm_state_walk *walk);
void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
struct xfrm_state *xfrm_state_alloc(struct net *net);
struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
Expand All @@ -1436,12 +1435,12 @@ struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
unsigned short family);
#ifdef CONFIG_XFRM_SUB_POLICY
int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
unsigned short family);
unsigned short family, struct net *net);
int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
unsigned short family);
#else
static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family)
int n, unsigned short family, struct net *net)
{
return -ENOSYS;
}
Expand Down Expand Up @@ -1553,7 +1552,7 @@ void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
int (*func)(struct xfrm_policy *, int, int, void*),
void *);
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
u8 type, int dir,
Expand All @@ -1576,7 +1575,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m);
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
Expand Down
15 changes: 10 additions & 5 deletions net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,9 @@ static int pfkey_dump_sa(struct pfkey_sock *pfk)

static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
{
xfrm_state_walk_done(&pfk->dump.u.state);
struct net *net = sock_net(&pfk->sk);

xfrm_state_walk_done(&pfk->dump.u.state, net);
}

static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
Expand Down Expand Up @@ -1861,7 +1863,7 @@ static u32 gen_reqid(struct net *net)
reqid = IPSEC_MANUAL_REQID_MAX+1;
xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
rc = xfrm_policy_walk(net, &walk, check_reqid, (void*)&reqid);
xfrm_policy_walk_done(&walk);
xfrm_policy_walk_done(&walk, net);
if (rc != -EEXIST)
return reqid;
} while (reqid != start);
Expand Down Expand Up @@ -2660,7 +2662,9 @@ static int pfkey_dump_sp(struct pfkey_sock *pfk)

static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
{
xfrm_policy_walk_done(&pfk->dump.u.policy);
struct net *net = sock_net((struct sock *)pfk);

xfrm_policy_walk_done(&pfk->dump.u.policy, net);
}

static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
Expand Down Expand Up @@ -3570,6 +3574,7 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
struct sk_buff *skb = NULL;
struct sadb_msg *hdr = NULL;
int err;
struct net *net = sock_net(sk);

err = -EOPNOTSUPP;
if (msg->msg_flags & MSG_OOB)
Expand All @@ -3592,9 +3597,9 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
if (!hdr)
goto out;

mutex_lock(&xfrm_cfg_mutex);
mutex_lock(&net->xfrm.xfrm_cfg_mutex);
err = pfkey_process(sk, skb, hdr);
mutex_unlock(&xfrm_cfg_mutex);
mutex_unlock(&net->xfrm.xfrm_cfg_mutex);

out:
if (err && hdr && pfkey_error(hdr, err, sk) == 0)
Expand Down
Loading

0 comments on commit 283bc9f

Please sign in to comment.