Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> --- net/xfrm/xfrm_policy.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 1785488..ea3456d 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -55,7 +55,6 @@ static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; static struct kmem_cache *xfrm_dst_cache __read_mostly; -static struct work_struct xfrm_policy_gc_work; static HLIST_HEAD(xfrm_policy_gc_list); static DEFINE_SPINLOCK(xfrm_policy_gc_lock); @@ -296,6 +295,7 @@ static void xfrm_policy_gc_task(struct work_struct *work) hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) xfrm_policy_gc_kill(policy); } +static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task); /* Rule must be locked. Release descentant resources, announce * entry dead. The rule must be unlinked from lists to the moment. @@ -2425,7 +2425,6 @@ static void __init xfrm_policy_init(void) } INIT_LIST_HEAD(&xfrm_policy_all); - INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); register_netdevice_notifier(&xfrm_dev_notifier); } -- 1.5.6.5 --
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/net_namespace.h | 4 +++
include/net/netns/xfrm.h | 7 ++++++
include/net/xfrm.h | 3 +-
net/xfrm/xfrm_policy.c | 45 ++++++++++++++++++++++++++++++++++++++----
net/xfrm/xfrm_state.c | 7 +++++-
5 files changed, 59 insertions(+), 7 deletions(-)
create mode 100644 include/net/netns/xfrm.h
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 3195577..6fc13d9 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -19,6 +19,7 @@
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netns/conntrack.h>
#endif
+#include <net/netns/xfrm.h>
struct proc_dir_entry;
struct net_device;
@@ -74,6 +75,9 @@ struct net {
struct netns_ct ct;
#endif
#endif
+#ifdef CONFIG_XFRM
+ struct netns_xfrm xfrm;
+#endif
struct net_generic *gen;
};
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
new file mode 100644
index 0000000..1cb0024
--- /dev/null
+++ b/include/net/netns/xfrm.h
@@ -0,0 +1,7 @@
+#ifndef __NETNS_XFRM_H
+#define __NETNS_XFRM_H
+
+struct netns_xfrm {
+};
+
+#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 45e11b3..9107d6f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1269,7 +1269,8 @@ struct xfrm6_tunnel {
extern void xfrm_init(void);
extern void xfrm4_init(void);
-extern void xfrm_state_init(void);
+extern int xfrm_state_init(struct net *net);
+extern void xfrm_state_fini(struct net *net);
extern void xfrm4_state_init(void);
#ifdef CONFIG_XFRM
extern int xfrm6_init(void);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ea3456d..8e7671b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2394,12 +2394,13 @@ static int __init xfrm_statistics_init(void)
}
#endif
-static void __init xfrm_policy_init(void)
+static int __net_init xfrm_policy_init(struct net *net)
...To avoid unnecessary complications with passing netns around.
* set once, very early after allocating
* once set, never changes
For a while create every xfrm_state in init_net.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 10 +++++++++-
net/ipv4/ipcomp.c | 2 +-
net/ipv6/ipcomp6.c | 2 +-
net/key/af_key.c | 2 +-
net/xfrm/xfrm_state.c | 9 +++++----
net/xfrm/xfrm_user.c | 4 ++--
6 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9107d6f..9da8903 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -130,6 +130,9 @@ struct xfrm_state_walk {
/* Full description of state of transformer. */
struct xfrm_state
{
+#ifdef CONFIG_NET_NS
+ struct net *xs_net;
+#endif
union {
struct hlist_node gclist;
struct hlist_node bydst;
@@ -223,6 +226,11 @@ struct xfrm_state
void *data;
};
+static inline struct net *xs_net(struct xfrm_state *x)
+{
+ return read_pnet(&x->xs_net);
+}
+
/* xflags - make enum if more show up */
#define XFRM_TIME_DEFER 1
@@ -1296,7 +1304,7 @@ extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
extern int xfrm_state_walk(struct xfrm_state_walk *walk,
int (*func)(struct xfrm_state *, int, void*), void *);
extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
-extern struct xfrm_state *xfrm_state_alloc(void);
+extern struct xfrm_state *xfrm_state_alloc(struct net *net);
extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
struct flowi *fl, struct xfrm_tmpl *tmpl,
struct xfrm_policy *pol, int *err,
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index ec8264a..0a35f1b 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -49,7 +49,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
{
struct xfrm_state *t;
- t = xfrm_state_alloc();
+ t = ...This is done to get
a) simple "something leaked" check
b) cover possible DoSes when other netns puts many, many xfrm_states
onto a list.
c) not miss "alien xfrm_state" check in some of list iterators in future.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 3 +++
net/xfrm/xfrm_state.c | 14 ++++++++------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 1cb0024..6ae234a 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -1,7 +1,10 @@
#ifndef __NETNS_XFRM_H
#define __NETNS_XFRM_H
+#include <linux/list.h>
+
struct netns_xfrm {
+ struct list_head state_all;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 81bde76..85bb854 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,6 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
* Main use is finding SA after policy selected tunnel or transport mode.
* Also, it can be used by ah/esp icmp error handler to find offending SA.
*/
-static LIST_HEAD(xfrm_state_all);
static struct hlist_head *xfrm_state_bydst __read_mostly;
static struct hlist_head *xfrm_state_bysrc __read_mostly;
static struct hlist_head *xfrm_state_byspi __read_mostly;
@@ -855,7 +854,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
if (km_query(x, tmpl, pol) == 0) {
x->km.state = XFRM_STATE_ACQ;
- list_add(&x->km.all, &xfrm_state_all);
+ list_add(&x->km.all, &init_net.xfrm.state_all);
hlist_add_head(&x->bydst, xfrm_state_bydst+h);
h = xfrm_src_hash(daddr, saddr, family);
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
@@ -924,7 +923,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
x->genid = ++xfrm_state_genid;
- list_add(&x->km.all, &xfrm_state_all);
+ list_add(&x->km.all, &init_net.xfrm.state_all);
h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
x->props.reqid, ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 9 ++++++++
net/xfrm/xfrm_state.c | 50 +++++++++++++++++++++++----------------------
2 files changed, 35 insertions(+), 24 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 6ae234a..02487b3 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -5,6 +5,15 @@
struct netns_xfrm {
struct list_head state_all;
+ /*
+ * Hash table to find appropriate SA towards given target (endpoint of
+ * tunnel or destination of transport mode) allowed by selector.
+ *
+ * Main use is finding SA after policy selected tunnel or transport
+ * mode. Also, it can be used by ah/esp icmp error handler to find
+ * offending SA.
+ */
+ struct hlist_head *state_bydst;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 85bb854..08b7889 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -44,13 +44,6 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30;
static DEFINE_SPINLOCK(xfrm_state_lock);
-/* Hash table to find appropriate SA towards given target (endpoint
- * of tunnel or destination of transport mode) allowed by selector.
- *
- * Main use is finding SA after policy selected tunnel or transport mode.
- * Also, it can be used by ah/esp icmp error handler to find offending SA.
- */
-static struct hlist_head *xfrm_state_bydst __read_mostly;
static struct hlist_head *xfrm_state_bysrc __read_mostly;
static struct hlist_head *xfrm_state_byspi __read_mostly;
static unsigned int xfrm_state_hmask __read_mostly;
@@ -157,15 +150,15 @@ static void xfrm_hash_resize(struct work_struct *__unused)
nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
for (i = xfrm_state_hmask; i >= 0; i--)
- xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi,
+ xfrm_hash_transfer(init_net.xfrm.state_bydst+i, ndst, nsrc, nspi,
nhashmask);
- odst = xfrm_state_bydst;
+ odst = ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 23 ++++++++++++++---------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 02487b3..bfcd5a3 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -14,6 +14,7 @@ struct netns_xfrm {
* offending SA.
*/
struct hlist_head *state_bydst;
+ struct hlist_head *state_bysrc;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 08b7889..52d828b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -44,7 +44,6 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30;
static DEFINE_SPINLOCK(xfrm_state_lock);
-static struct hlist_head *xfrm_state_bysrc __read_mostly;
static struct hlist_head *xfrm_state_byspi __read_mostly;
static unsigned int xfrm_state_hmask __read_mostly;
static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
@@ -154,12 +153,12 @@ static void xfrm_hash_resize(struct work_struct *__unused)
nhashmask);
odst = init_net.xfrm.state_bydst;
- osrc = xfrm_state_bysrc;
+ osrc = init_net.xfrm.state_bysrc;
ospi = xfrm_state_byspi;
ohashmask = xfrm_state_hmask;
init_net.xfrm.state_bydst = ndst;
- xfrm_state_bysrc = nsrc;
+ init_net.xfrm.state_bysrc = nsrc;
xfrm_state_byspi = nspi;
xfrm_state_hmask = nhashmask;
@@ -712,7 +711,7 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm
struct xfrm_state *x;
struct hlist_node *entry;
- hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
+ hlist_for_each_entry(x, entry, init_net.xfrm.state_bysrc+h, bysrc) {
if (x->props.family != family ||
x->id.proto != proto)
continue;
@@ -850,7 +849,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
list_add(&x->km.all, &init_net.xfrm.state_all);
hlist_add_head(&x->bydst, ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 21 +++++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index bfcd5a3..b05ca3f 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -15,6 +15,7 @@ struct netns_xfrm {
*/
struct hlist_head *state_bydst;
struct hlist_head *state_bysrc;
+ struct hlist_head *state_byspi;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 52d828b..66ca1ef 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -44,7 +44,6 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30;
static DEFINE_SPINLOCK(xfrm_state_lock);
-static struct hlist_head *xfrm_state_byspi __read_mostly;
static unsigned int xfrm_state_hmask __read_mostly;
static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
static unsigned int xfrm_state_num;
@@ -154,12 +153,12 @@ static void xfrm_hash_resize(struct work_struct *__unused)
odst = init_net.xfrm.state_bydst;
osrc = init_net.xfrm.state_bysrc;
- ospi = xfrm_state_byspi;
+ ospi = init_net.xfrm.state_byspi;
ohashmask = xfrm_state_hmask;
init_net.xfrm.state_bydst = ndst;
init_net.xfrm.state_bysrc = nsrc;
- xfrm_state_byspi = nspi;
+ init_net.xfrm.state_byspi = nspi;
xfrm_state_hmask = nhashmask;
spin_unlock_bh(&xfrm_state_lock);
@@ -679,7 +678,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi,
struct xfrm_state *x;
struct hlist_node *entry;
- hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) {
+ hlist_for_each_entry(x, entry, init_net.xfrm.state_byspi+h, byspi) {
if (x->props.family != family ||
x->id.spi != spi ||
x->id.proto != proto)
@@ -852,7 +851,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
hlist_add_head(&x->bysrc, init_net.xfrm.state_bysrc+h);
...Since hashtables are per-netns, they can be independently resized.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 31 +++++++++++++++----------------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index b05ca3f..dbbc0e9 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -16,6 +16,7 @@ struct netns_xfrm {
struct hlist_head *state_bydst;
struct hlist_head *state_bysrc;
struct hlist_head *state_byspi;
+ unsigned int state_hmask;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 66ca1ef..de08ed9 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -44,7 +44,6 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30;
static DEFINE_SPINLOCK(xfrm_state_lock);
-static unsigned int xfrm_state_hmask __read_mostly;
static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
static unsigned int xfrm_state_num;
static unsigned int xfrm_state_genid;
@@ -64,20 +63,20 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
u32 reqid,
unsigned short family)
{
- return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
+ return __xfrm_dst_hash(daddr, saddr, reqid, family, init_net.xfrm.state_hmask);
}
static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family)
{
- return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask);
+ return __xfrm_src_hash(daddr, saddr, family, init_net.xfrm.state_hmask);
}
static inline unsigned int
xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
{
- return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask);
+ return __xfrm_spi_hash(daddr, spi, proto, family, init_net.xfrm.state_hmask);
}
static void xfrm_hash_transfer(struct hlist_head *list,
@@ -113,7 ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 14 +++++++-------
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index dbbc0e9..492b471 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -17,6 +17,7 @@ struct netns_xfrm {
struct hlist_head *state_bysrc;
struct hlist_head *state_byspi;
unsigned int state_hmask;
+ unsigned int state_num;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index de08ed9..7ecf6ee 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -45,7 +45,6 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30;
static DEFINE_SPINLOCK(xfrm_state_lock);
static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
-static unsigned int xfrm_state_num;
static unsigned int xfrm_state_genid;
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
@@ -548,7 +547,7 @@ int __xfrm_state_delete(struct xfrm_state *x)
hlist_del(&x->bysrc);
if (x->id.spi)
hlist_del(&x->byspi);
- xfrm_state_num--;
+ init_net.xfrm.state_num--;
spin_unlock(&xfrm_state_lock);
/* All xfrm_state objects are created by xfrm_state_alloc.
@@ -650,7 +649,7 @@ EXPORT_SYMBOL(xfrm_state_flush);
void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
{
spin_lock_bh(&xfrm_state_lock);
- si->sadcnt = xfrm_state_num;
+ si->sadcnt = init_net.xfrm.state_num;
si->sadhcnt = init_net.xfrm.state_hmask;
si->sadhmcnt = xfrm_state_hashmax;
spin_unlock_bh(&xfrm_state_lock);
@@ -754,7 +753,7 @@ static void xfrm_hash_grow_check(int have_hash_collision)
{
if (have_hash_collision &&
(init_net.xfrm.state_hmask + 1) < xfrm_state_hashmax &&
- xfrm_state_num > init_net.xfrm.state_hmask)
+ init_net.xfrm.state_num > init_net.xfrm.state_hmask)
schedule_work(&xfrm_hash_work);
}
@@ -855,7 +854,7 @@ ...All of this is implicit passing which netns's hashes should be resized.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 2 ++
net/xfrm/xfrm_state.c | 35 +++++++++++++++++------------------
2 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 492b471..bd68802 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -2,6 +2,7 @@
#define __NETNS_XFRM_H
#include <linux/list.h>
+#include <linux/workqueue.h>
struct netns_xfrm {
struct list_head state_all;
@@ -18,6 +19,7 @@ struct netns_xfrm {
struct hlist_head *state_byspi;
unsigned int state_hmask;
unsigned int state_num;
+ struct work_struct state_hash_work;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 7ecf6ee..1b2a72c 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -109,16 +109,16 @@ static void xfrm_hash_transfer(struct hlist_head *list,
}
}
-static unsigned long xfrm_hash_new_size(void)
+static unsigned long xfrm_hash_new_size(unsigned int state_hmask)
{
- return ((init_net.xfrm.state_hmask + 1) << 1) *
- sizeof(struct hlist_head);
+ return ((state_hmask + 1) << 1) * sizeof(struct hlist_head);
}
static DEFINE_MUTEX(hash_resize_mutex);
-static void xfrm_hash_resize(struct work_struct *__unused)
+static void xfrm_hash_resize(struct work_struct *work)
{
+ struct net *net = container_of(work, struct net, xfrm.state_hash_work);
struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi;
unsigned long nsize, osize;
unsigned int nhashmask, ohashmask;
@@ -126,7 +126,7 @@ static void xfrm_hash_resize(struct work_struct *__unused)
mutex_lock(&hash_resize_mutex);
- nsize = xfrm_hash_new_size();
+ nsize = xfrm_hash_new_size(net->xfrm.state_hmask);
ndst = xfrm_hash_alloc(nsize);
if (!ndst)
goto out_unlock;
@@ -145,19 +145,19 @@ static void xfrm_hash_resize(struct work_struct ...km_waitq is going to be made per-netns to disallow spurious wakeups
in __xfrm_lookup().
To not wakeup after every garbage-collected xfrm_state (which potentially
can be from different netns) make state GC list per-netns.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index bd68802..8ceb765 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -20,6 +20,7 @@ struct netns_xfrm {
unsigned int state_hmask;
unsigned int state_num;
struct work_struct state_hash_work;
+ struct hlist_head state_gc_list;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1b2a72c..864a974 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -177,7 +177,6 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
static struct work_struct xfrm_state_gc_work;
-static HLIST_HEAD(xfrm_state_gc_list);
static DEFINE_SPINLOCK(xfrm_state_gc_lock);
int __xfrm_state_delete(struct xfrm_state *x);
@@ -394,7 +393,7 @@ static void xfrm_state_gc_task(struct work_struct *data)
struct hlist_head gc_list;
spin_lock_bh(&xfrm_state_gc_lock);
- hlist_move_list(&xfrm_state_gc_list, &gc_list);
+ hlist_move_list(&init_net.xfrm.state_gc_list, &gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
@@ -527,7 +526,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
WARN_ON(x->km.state != XFRM_STATE_DEAD);
spin_lock_bh(&xfrm_state_gc_lock);
- hlist_add_head(&x->gclist, &xfrm_state_gc_list);
+ hlist_add_head(&x->gclist, &init_net.xfrm.state_gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
schedule_work(&xfrm_state_gc_work);
}
@@ -2088,6 +2087,7 @@ int __net_init xfrm_state_init(struct net *net)
...State GC is per-netns, and this is part of it.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_state.c | 10 +++++-----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 8ceb765..8055535 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -21,6 +21,7 @@ struct netns_xfrm {
unsigned int state_num;
struct work_struct state_hash_work;
struct hlist_head state_gc_list;
+ struct work_struct state_gc_work;
};
#endif
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 864a974..69c0b06 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -176,7 +176,6 @@ EXPORT_SYMBOL(km_waitq);
static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
-static struct work_struct xfrm_state_gc_work;
static DEFINE_SPINLOCK(xfrm_state_gc_lock);
int __xfrm_state_delete(struct xfrm_state *x);
@@ -386,14 +385,15 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
kfree(x);
}
-static void xfrm_state_gc_task(struct work_struct *data)
+static void xfrm_state_gc_task(struct work_struct *work)
{
+ struct net *net = container_of(work, struct net, xfrm.state_gc_work);
struct xfrm_state *x;
struct hlist_node *entry, *tmp;
struct hlist_head gc_list;
spin_lock_bh(&xfrm_state_gc_lock);
- hlist_move_list(&init_net.xfrm.state_gc_list, &gc_list);
+ hlist_move_list(&net->xfrm.state_gc_list, &gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
@@ -528,7 +528,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
spin_lock_bh(&xfrm_state_gc_lock);
hlist_add_head(&x->gclist, &init_net.xfrm.state_gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
- schedule_work(&xfrm_state_gc_work);
+ schedule_work(&init_net.xfrm.state_gc_work);
}
EXPORT_SYMBOL(__xfrm_state_destroy);
@@ ...Dissalow spurious wakeups in __xfrm_lookup().
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 3 +++
include/net/xfrm.h | 1 -
net/key/af_key.c | 2 +-
net/xfrm/xfrm_policy.c | 4 ++--
net/xfrm/xfrm_state.c | 16 +++++++---------
5 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 8055535..2a383c8 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -2,6 +2,7 @@
#define __NETNS_XFRM_H
#include <linux/list.h>
+#include <linux/wait.h>
#include <linux/workqueue.h>
struct netns_xfrm {
@@ -22,6 +23,8 @@ struct netns_xfrm {
struct work_struct state_hash_work;
struct hlist_head state_gc_list;
struct work_struct state_gc_work;
+
+ wait_queue_head_t km_waitq;
};
#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9da8903..0d4353c 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1459,7 +1459,6 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_kmaddress *k);
#endif
-extern wait_queue_head_t km_waitq;
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index bde8aad..f202ba6 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1411,7 +1411,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
spin_lock_bh(&x->lock);
if (x->km.state == XFRM_STATE_ACQ) {
x->km.state = XFRM_STATE_ERROR;
- wake_up(&km_waitq);
+ wake_up(&init_net.xfrm.km_waitq);
}
spin_unlock_bh(&x->lock);
xfrm_state_put(x);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8e7671b..cf2bf3a 100644
--- a/net/xfrm/xfrm_policy.c
+++ ...Again, to avoid complications with passing netns when not necessary.
Again, ->xp_net is set-once field, once set it never changes.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 10 +++++++++-
net/key/af_key.c | 4 ++--
net/xfrm/xfrm_policy.c | 5 +++--
net/xfrm/xfrm_user.c | 4 ++--
4 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0d4353c..1ab1756 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -475,6 +475,9 @@ struct xfrm_policy_walk {
struct xfrm_policy
{
+#ifdef CONFIG_NET_NS
+ struct net *xp_net;
+#endif
struct hlist_node bydst;
struct hlist_node byidx;
@@ -499,6 +502,11 @@ struct xfrm_policy
struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
};
+static inline struct net *xp_net(struct xfrm_policy *xp)
+{
+ return read_pnet(&xp->xp_net);
+}
+
struct xfrm_kmaddress {
xfrm_address_t local;
xfrm_address_t remote;
@@ -1425,7 +1433,7 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
}
#endif
-struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
+struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
diff --git a/net/key/af_key.c b/net/key/af_key.c
index f202ba6..036315d 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2174,7 +2174,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX)
return -EINVAL;
- xp = xfrm_policy_alloc(GFP_KERNEL);
+ xp = xfrm_policy_alloc(&init_net, GFP_KERNEL);
if (xp == NULL)
return -ENOBUFS;
@@ -3141,7 +3141,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
(!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 2 ++
net/xfrm/xfrm_policy.c | 12 ++++++------
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 2a383c8..6648924 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -25,6 +25,8 @@ struct netns_xfrm {
struct work_struct state_gc_work;
wait_queue_head_t km_waitq;
+
+ struct list_head policy_all;
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3eccefa..aabc7f2 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -46,7 +46,6 @@ EXPORT_SYMBOL(xfrm_cfg_mutex);
static DEFINE_RWLOCK(xfrm_policy_lock);
-static struct list_head xfrm_policy_all;
unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
EXPORT_SYMBOL(xfrm_policy_count);
@@ -615,7 +614,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
policy->curlft.use_time = 0;
if (!mod_timer(&policy->timer, jiffies + HZ))
xfrm_pol_hold(policy);
- list_add(&policy->walk.all, &xfrm_policy_all);
+ list_add(&policy->walk.all, &init_net.xfrm.policy_all);
write_unlock_bh(&xfrm_policy_lock);
if (delpol)
@@ -881,10 +880,10 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk,
write_lock_bh(&xfrm_policy_lock);
if (list_empty(&walk->walk.all))
- x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all);
+ x = list_first_entry(&init_net.xfrm.policy_all, struct xfrm_policy_walk_entry, all);
else
x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all);
- list_for_each_entry_from(x, &xfrm_policy_all, all) {
+ list_for_each_entry_from(x, &init_net.xfrm.policy_all, all) {
if (x->dead)
continue;
pol = container_of(x, struct xfrm_policy, walk);
@@ -1086,7 +1085,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
struct hlist_head *chain = policy_hash_bysel(&pol->selector,
...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_policy.c | 28 ++++++++++++++++++----------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 6648924..5cd7d06 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -27,6 +27,7 @@ struct netns_xfrm {
wait_queue_head_t km_waitq;
struct list_head policy_all;
+ struct hlist_head *policy_byidx;
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index aabc7f2..700cdd7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -329,7 +329,6 @@ struct xfrm_policy_hash {
static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2];
static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly;
-static struct hlist_head *xfrm_policy_byidx __read_mostly;
static unsigned int xfrm_idx_hmask __read_mostly;
static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
@@ -438,7 +437,7 @@ static void xfrm_byidx_resize(int total)
unsigned int hmask = xfrm_idx_hmask;
unsigned int nhashmask = xfrm_new_hash_mask(hmask);
unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
- struct hlist_head *oidx = xfrm_policy_byidx;
+ struct hlist_head *oidx = init_net.xfrm.policy_byidx;
struct hlist_head *nidx = xfrm_hash_alloc(nsize);
int i;
@@ -450,7 +449,7 @@ static void xfrm_byidx_resize(int total)
for (i = hmask; i >= 0; i--)
xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask);
- xfrm_policy_byidx = nidx;
+ init_net.xfrm.policy_byidx = nidx;
xfrm_idx_hmask = nhashmask;
write_unlock_bh(&xfrm_policy_lock);
@@ -536,7 +535,7 @@ static u32 xfrm_gen_index(int dir)
idx_generator += 8;
if (idx == 0)
idx = 8;
- list = xfrm_policy_byidx + idx_hash(idx);
+ list = init_net.xfrm.policy_byidx + idx_hash(idx);
found = 0;
hlist_for_each_entry(p, entry, list, byidx) ...Per-netns hashes are independently resizeable.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_policy.c | 15 +++++++--------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 5cd7d06..42dc318 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -28,6 +28,7 @@ struct netns_xfrm {
struct list_head policy_all;
struct hlist_head *policy_byidx;
+ unsigned int policy_idx_hmask;
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 700cdd7..9e37a44 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -329,12 +329,11 @@ struct xfrm_policy_hash {
static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2];
static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly;
-static unsigned int xfrm_idx_hmask __read_mostly;
static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
static inline unsigned int idx_hash(u32 index)
{
- return __idx_hash(index, xfrm_idx_hmask);
+ return __idx_hash(index, init_net.xfrm.policy_idx_hmask);
}
static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
@@ -434,7 +433,7 @@ static void xfrm_bydst_resize(int dir)
static void xfrm_byidx_resize(int total)
{
- unsigned int hmask = xfrm_idx_hmask;
+ unsigned int hmask = init_net.xfrm.policy_idx_hmask;
unsigned int nhashmask = xfrm_new_hash_mask(hmask);
unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
struct hlist_head *oidx = init_net.xfrm.policy_byidx;
@@ -450,7 +449,7 @@ static void xfrm_byidx_resize(int total)
xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask);
init_net.xfrm.policy_byidx = nidx;
- xfrm_idx_hmask = nhashmask;
+ init_net.xfrm.policy_idx_hmask = nhashmask;
write_unlock_bh(&xfrm_policy_lock);
@@ -474,7 +473,7 @@ static inline int ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 2 ++
net/xfrm/xfrm_policy.c | 20 ++++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 42dc318..c756831 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -4,6 +4,7 @@
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <linux/xfrm.h>
struct netns_xfrm {
struct list_head state_all;
@@ -29,6 +30,7 @@ struct netns_xfrm {
struct list_head policy_all;
struct hlist_head *policy_byidx;
unsigned int policy_idx_hmask;
+ struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 9e37a44..ba4e95b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -327,7 +327,6 @@ struct xfrm_policy_hash {
unsigned int hmask;
};
-static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2];
static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly;
static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
@@ -342,7 +341,7 @@ static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned
unsigned int hash = __sel_hash(sel, family, hmask);
return (hash == hmask + 1 ?
- &xfrm_policy_inexact[dir] :
+ &init_net.xfrm.policy_inexact[dir] :
xfrm_policy_bydst[dir].table + hash);
}
@@ -752,7 +751,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
int i;
hlist_for_each_entry(pol, entry,
- &xfrm_policy_inexact[dir], bydst) {
+ &init_net.xfrm.policy_inexact[dir], bydst) {
if (pol->type != type)
continue;
err = security_xfrm_policy_delete(pol->security);
@@ -810,7 +809,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
killed = 0;
again1:
hlist_for_each_entry(pol, entry,
- ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 6 +++++
net/xfrm/xfrm_policy.c | 57 ++++++++++++++++++++++++++-------------------
2 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index c756831..39cfa79 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -6,6 +6,11 @@
#include <linux/workqueue.h>
#include <linux/xfrm.h>
+struct xfrm_policy_hash {
+ struct hlist_head *table;
+ unsigned int hmask;
+};
+
struct netns_xfrm {
struct list_head state_all;
/*
@@ -31,6 +36,7 @@ struct netns_xfrm {
struct hlist_head *policy_byidx;
unsigned int policy_idx_hmask;
struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
+ struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ba4e95b..929b2fd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -322,12 +322,6 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
schedule_work(&xfrm_policy_gc_work);
}
-struct xfrm_policy_hash {
- struct hlist_head *table;
- unsigned int hmask;
-};
-
-static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly;
static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
static inline unsigned int idx_hash(u32 index)
@@ -337,20 +331,20 @@ static inline unsigned int idx_hash(u32 index)
static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
{
- unsigned int hmask = xfrm_policy_bydst[dir].hmask;
+ unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask;
unsigned int hash = __sel_hash(sel, family, hmask);
return (hash == hmask + 1 ?
&init_net.xfrm.policy_inexact[dir] :
- xfrm_policy_bydst[dir].table + hash);
+ init_net.xfrm.policy_bydst[dir].table + hash);
}
static struct hlist_head *policy_hash_direct(xfrm_address_t ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
include/net/xfrm.h | 6 ++----
net/xfrm/xfrm_policy.c | 34 ++++++++++++++++------------------
3 files changed, 19 insertions(+), 22 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 39cfa79..d5aadf0 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -37,6 +37,7 @@ struct netns_xfrm {
unsigned int policy_idx_hmask;
struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
+ unsigned int policy_count[XFRM_POLICY_MAX * 2];
};
#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1ab1756..8699620 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -559,8 +559,6 @@ struct xfrm_mgr
extern int xfrm_register_km(struct xfrm_mgr *km);
extern int xfrm_unregister_km(struct xfrm_mgr *km);
-extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
-
/*
* This structure is used for the duration where packets are being
* transformed by IPsec. As soon as the packet leaves IPsec the
@@ -999,7 +997,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
if (sk && sk->sk_policy[XFRM_POLICY_IN])
return __xfrm_policy_check(sk, ndir, skb, family);
- return (!xfrm_policy_count[dir] && !skb->sp) ||
+ return (!init_net.xfrm.policy_count[dir] && !skb->sp) ||
(skb->dst->flags & DST_NOPOLICY) ||
__xfrm_policy_check(sk, ndir, skb, family);
}
@@ -1051,7 +1049,7 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
- return !xfrm_policy_count[XFRM_POLICY_OUT] ||
+ return !init_net.xfrm.policy_count[XFRM_POLICY_OUT] ||
(skb->dst->flags & DST_NOXFRM) ||
__xfrm_route_forward(skb, family);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 929b2fd..630ec04 100644
--- ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_policy.c | 52 +++++++++++++++++++++++-----------------------
2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index d5aadf0..c53d173 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -38,6 +38,7 @@ struct netns_xfrm {
struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
unsigned int policy_count[XFRM_POLICY_MAX * 2];
+ struct work_struct policy_hash_work;
};
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 630ec04..1d30086 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -396,12 +396,12 @@ static unsigned long xfrm_new_hash_mask(unsigned int old_hmask)
return ((old_hmask + 1) << 1) - 1;
}
-static void xfrm_bydst_resize(int dir)
+static void xfrm_bydst_resize(struct net *net, int dir)
{
- unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask;
+ unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
unsigned int nhashmask = xfrm_new_hash_mask(hmask);
unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head);
- struct hlist_head *odst = init_net.xfrm.policy_bydst[dir].table;
+ struct hlist_head *odst = net->xfrm.policy_bydst[dir].table;
struct hlist_head *ndst = xfrm_hash_alloc(nsize);
int i;
@@ -413,20 +413,20 @@ static void xfrm_bydst_resize(int dir)
for (i = hmask; i >= 0; i--)
xfrm_dst_hash_transfer(odst + i, ndst, nhashmask);
- init_net.xfrm.policy_bydst[dir].table = ndst;
- init_net.xfrm.policy_bydst[dir].hmask = nhashmask;
+ net->xfrm.policy_bydst[dir].table = ndst;
+ net->xfrm.policy_bydst[dir].hmask = nhashmask;
write_unlock_bh(&xfrm_policy_lock);
xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
}
-static void xfrm_byidx_resize(int total)
+static void xfrm_byidx_resize(struct net ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_state.c | 44 +++++++++++++++++++++++---------------------
1 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 24bd89e..72b2956 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -57,25 +57,27 @@ static void xfrm_audit_state_replay(struct xfrm_state *x,
#define xfrm_audit_state_replay(x, s, sq) do { ; } while (0)
#endif /* CONFIG_AUDITSYSCALL */
-static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
+static inline unsigned int xfrm_dst_hash(struct net *net,
+ xfrm_address_t *daddr,
xfrm_address_t *saddr,
u32 reqid,
unsigned short family)
{
- return __xfrm_dst_hash(daddr, saddr, reqid, family, init_net.xfrm.state_hmask);
+ return __xfrm_dst_hash(daddr, saddr, reqid, family, net->xfrm.state_hmask);
}
-static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr,
+static inline unsigned int xfrm_src_hash(struct net *net,
+ xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family)
{
- return __xfrm_src_hash(daddr, saddr, family, init_net.xfrm.state_hmask);
+ return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask);
}
static inline unsigned int
-xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
+xfrm_spi_hash(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
{
- return __xfrm_spi_hash(daddr, spi, proto, family, init_net.xfrm.state_hmask);
+ return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask);
}
static void xfrm_hash_transfer(struct hlist_head *list,
@@ -666,7 +668,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
{
- unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
+ unsigned int h = ...Take netns from xfrm_state or xfrm_policy.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_policy.c | 15 +++++++-----
net/xfrm/xfrm_state.c | 59 +++++++++++++++++++++++++++--------------------
2 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1d30086..3d931f5 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1069,29 +1069,32 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
{
+ struct net *net = xp_net(pol);
struct hlist_head *chain = policy_hash_bysel(&pol->selector,
pol->family, dir);
- list_add(&pol->walk.all, &init_net.xfrm.policy_all);
+ list_add(&pol->walk.all, &net->xfrm.policy_all);
hlist_add_head(&pol->bydst, chain);
- hlist_add_head(&pol->byidx, init_net.xfrm.policy_byidx+idx_hash(pol->index));
- init_net.xfrm.policy_count[dir]++;
+ hlist_add_head(&pol->byidx, net->xfrm.policy_byidx+idx_hash(pol->index));
+ net->xfrm.policy_count[dir]++;
xfrm_pol_hold(pol);
- if (xfrm_bydst_should_resize(&init_net, dir, NULL))
- schedule_work(&init_net.xfrm.policy_hash_work);
+ if (xfrm_bydst_should_resize(net, dir, NULL))
+ schedule_work(&net->xfrm.policy_hash_work);
}
static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
int dir)
{
+ struct net *net = xp_net(pol);
+
if (hlist_unhashed(&pol->bydst))
return NULL;
hlist_del(&pol->bydst);
hlist_del(&pol->byidx);
list_del(&pol->walk.all);
- init_net.xfrm.policy_count[dir]--;
+ net->xfrm.policy_count[dir]--;
return pol;
}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 72b2956..f3f635d 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -412,6 +412,7 @@ static inline unsigned long make_jiffies(long secs)
static void xfrm_timer_handler(unsigned long data)
{
struct xfrm_state *x = (struct ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/key/af_key.c | 2 +-
net/xfrm/xfrm_state.c | 18 +++++++++---------
net/xfrm/xfrm_user.c | 2 +-
4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 8699620..e4bb672 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1363,7 +1363,7 @@ struct xfrmk_spdinfo {
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
-extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
+extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x,
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 036315d..e5d595a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1732,7 +1732,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
audit_info.loginuid = audit_get_loginuid(current);
audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = 0;
- err = xfrm_state_flush(proto, &audit_info);
+ err = xfrm_state_flush(&init_net, proto, &audit_info);
if (err)
return err;
c.data.proto = proto;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f3f635d..5f4c534 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -576,15 +576,15 @@ EXPORT_SYMBOL(xfrm_state_delete);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int
-xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info)
{
int i, err = 0;
- for (i = 0; i <= init_net.xfrm.state_hmask; i++) {
+ for (i = 0; i <= net->xfrm.state_hmask; i++) {
struct hlist_node *entry;
struct xfrm_state *x;
...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> --- include/net/xfrm.h | 4 ++-- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv4/ipcomp.c | 4 ++-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/ipcomp6.c | 4 ++-- net/ipv6/xfrm6_input.c | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_state.c | 34 +++++++++++++++++++--------------- net/xfrm/xfrm_user.c | 12 ++++++------ 12 files changed, 38 insertions(+), 34 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e4bb672..15136c5 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1323,8 +1323,8 @@ extern int xfrm_state_check_expire(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_add(struct xfrm_state *x); extern int xfrm_state_update(struct xfrm_state *x); -extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); -extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); #ifdef CONFIG_XFRM_SUB_POLICY extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, unsigned short family); diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 992ecd8..750426b 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -209,7 +209,7 @@ static void ah4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); + x = xfrm_state_lookup(&init_net, (xfrm_address_t ...
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_state.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index afde474..cd51e4e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1527,8 +1527,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
}
if (x->id.spi) {
spin_lock_bh(&xfrm_state_lock);
- h = xfrm_spi_hash(&init_net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
- hlist_add_head(&x->byspi, init_net.xfrm.state_byspi+h);
+ h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
+ hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
spin_unlock_bh(&xfrm_state_lock);
err = 0;
--
1.5.6.5
--
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 7 +++--
net/core/pktgen.c | 3 +-
net/key/af_key.c | 6 ++--
net/xfrm/xfrm_state.c | 73 +++++++++++++++++++++++++-----------------------
net/xfrm/xfrm_user.c | 4 +-
5 files changed, 49 insertions(+), 44 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 15136c5..4cbd055 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1315,7 +1315,8 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
struct flowi *fl, struct xfrm_tmpl *tmpl,
struct xfrm_policy *pol, int *err,
unsigned short family);
-extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr,
+extern struct xfrm_state * xfrm_stateonly_find(struct net *net,
+ xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family,
u8 mode, u8 proto, u32 reqid);
@@ -1361,7 +1362,7 @@ struct xfrmk_spdinfo {
u32 spdhmcnt;
};
-extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
+extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
@@ -1446,7 +1447,7 @@ struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
-struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
+struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
diff --git a/net/core/pktgen.c ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/key/af_key.c | 2 +-
net/xfrm/xfrm_state.c | 6 +++---
net/xfrm/xfrm_user.c | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4cbd055..40ed487 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1307,7 +1307,7 @@ extern int xfrm_proc_init(void);
#endif
extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
-extern int xfrm_state_walk(struct xfrm_state_walk *walk,
+extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
int (*func)(struct xfrm_state *, int, void*), void *);
extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
extern struct xfrm_state *xfrm_state_alloc(struct net *net);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 4ef0827..b74d939 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1776,7 +1776,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
static int pfkey_dump_sa(struct pfkey_sock *pfk)
{
- return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
+ return xfrm_state_walk(&init_net, &pfk->dump.u.state, dump_sa, (void *) pfk);
}
static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0d974fc..ea340bb 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1544,7 +1544,7 @@ unlock:
}
EXPORT_SYMBOL(xfrm_alloc_spi);
-int xfrm_state_walk(struct xfrm_state_walk *walk,
+int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
int (*func)(struct xfrm_state *, int, void*),
void *data)
{
@@ -1557,10 +1557,10 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
spin_lock_bh(&xfrm_state_lock);
if (list_empty(&walk->all))
- x = list_first_entry(&init_net.xfrm.state_all, struct xfrm_state_walk, all);
+ x = list_first_entry(&net->xfrm.state_all, struct ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_policy.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3d931f5..aefbb56 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -321,9 +321,9 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024;
-static inline unsigned int idx_hash(u32 index)
+static inline unsigned int idx_hash(struct net *net, u32 index)
{
- return __idx_hash(index, init_net.xfrm.policy_idx_hmask);
+ return __idx_hash(index, net->xfrm.policy_idx_hmask);
}
static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
@@ -523,7 +523,7 @@ static u32 xfrm_gen_index(int dir)
idx_generator += 8;
if (idx == 0)
idx = 8;
- list = init_net.xfrm.policy_byidx + idx_hash(idx);
+ list = init_net.xfrm.policy_byidx + idx_hash(&init_net, idx);
found = 0;
hlist_for_each_entry(p, entry, list, byidx) {
if (p->index == idx) {
@@ -596,7 +596,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
init_net.xfrm.policy_count[dir]--;
}
policy->index = delpol ? delpol->index : xfrm_gen_index(dir);
- hlist_add_head(&policy->byidx, init_net.xfrm.policy_byidx+idx_hash(policy->index));
+ hlist_add_head(&policy->byidx, init_net.xfrm.policy_byidx+idx_hash(&init_net, policy->index));
policy->curlft.add_time = get_seconds();
policy->curlft.use_time = 0;
if (!mod_timer(&policy->timer, jiffies + HZ))
@@ -698,7 +698,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
*err = 0;
write_lock_bh(&xfrm_policy_lock);
- chain = init_net.xfrm.policy_byidx + idx_hash(id);
+ chain = init_net.xfrm.policy_byidx + idx_hash(&init_net, id);
ret = NULL;
hlist_for_each_entry(pol, entry, chain, byidx) {
if (pol->type == type && pol->index == id) {
@@ ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_policy.c | 46 ++++++++++++++++++++++++----------------------
1 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index aefbb56..11fee87 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -326,22 +326,22 @@ static inline unsigned int idx_hash(struct net *net, u32 index)
return __idx_hash(index, net->xfrm.policy_idx_hmask);
}
-static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir)
+static struct hlist_head *policy_hash_bysel(struct net *net, struct xfrm_selector *sel, unsigned short family, int dir)
{
- unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask;
+ unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
unsigned int hash = __sel_hash(sel, family, hmask);
return (hash == hmask + 1 ?
- &init_net.xfrm.policy_inexact[dir] :
- init_net.xfrm.policy_bydst[dir].table + hash);
+ &net->xfrm.policy_inexact[dir] :
+ net->xfrm.policy_bydst[dir].table + hash);
}
-static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir)
+static struct hlist_head *policy_hash_direct(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir)
{
- unsigned int hmask = init_net.xfrm.policy_bydst[dir].hmask;
+ unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
unsigned int hash = __addr_hash(daddr, saddr, family, hmask);
- return init_net.xfrm.policy_bydst[dir].table + hash;
+ return net->xfrm.policy_bydst[dir].table + hash;
}
static void xfrm_dst_hash_transfer(struct hlist_head *list,
@@ -508,7 +508,7 @@ static void xfrm_hash_resize(struct work_struct *work)
/* Generate new index... KAME seems to generate them ordered by cost
* of an absolute inpredictability of ordering of rules. This will not pass. */
-static u32 xfrm_gen_index(int dir)
+static u32 ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/key/af_key.c | 2 +-
net/xfrm/xfrm_policy.c | 22 +++++++++++-----------
net/xfrm/xfrm_user.c | 2 +-
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 40ed487..766cc71 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1444,7 +1444,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
-int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto,
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b74d939..0f44856 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2686,7 +2686,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
audit_info.loginuid = audit_get_loginuid(current);
audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = 0;
- err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ err = xfrm_policy_flush(&init_net, XFRM_POLICY_TYPE_MAIN, &audit_info);
if (err)
return err;
c.data.type = XFRM_POLICY_TYPE_MAIN;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 11fee87..7c264a7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -732,7 +732,7 @@ EXPORT_SYMBOL(xfrm_policy_byid);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int
-xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info)
{
int dir, err = 0;
@@ -742,7 +742,7 @@ ...Add netns parameter to xfrm_policy_bysel_ctx(), xfrm_policy_byidx(). Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> --- include/net/xfrm.h | 4 ++-- net/key/af_key.c | 6 +++--- net/xfrm/xfrm_policy.c | 14 +++++++------- net/xfrm/xfrm_user.c | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 766cc71..ec2b7a9 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1439,11 +1439,11 @@ extern int xfrm_policy_walk(struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *); extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, +struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err); -struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); +struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err); int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); diff --git a/net/key/af_key.c b/net/key/af_key.c index 0f44856..ca26811 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2324,7 +2324,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg return err; } - xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, + xp = xfrm_policy_bysel_ctx(&init_net, XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir - 1, &sel, pol_ctx, 1, &err); security_xfrm_policy_free(pol_ctx); @@ -2571,8 +2571,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return -EINVAL; delete = (hdr->sadb_msg_type == ...
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/key/af_key.c | 4 ++--
net/xfrm/xfrm_policy.c | 6 +++---
net/xfrm/xfrm_user.c | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index ec2b7a9..1dc4ff0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1435,7 +1435,7 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
-extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
+extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
int (*func)(struct xfrm_policy *, int, int, void*), void *);
extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ca26811..a0d8498 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1846,7 +1846,7 @@ static u32 gen_reqid(void)
if (reqid == 0)
reqid = IPSEC_MANUAL_REQID_MAX+1;
xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
- rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid);
+ rc = xfrm_policy_walk(&init_net, &walk, check_reqid, (void*)&reqid);
xfrm_policy_walk_done(&walk);
if (rc != -EEXIST)
return reqid;
@@ -2633,7 +2633,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
static int pfkey_dump_sp(struct pfkey_sock *pfk)
{
- return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
+ return xfrm_policy_walk(&init_net, &pfk->dump.u.policy, dump_sp, (void *) pfk);
}
static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 96895ef..6165218 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -851,7 +851,7 @@ ...Pass netns to xfrm_lookup()/__xfrm_lookup(). For that pass netns
to flow_cache_lookup() and resolver callback.
Take it from socket or netdevice. Stub DECnet to init_net.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/dst.h | 16 ++++++++--------
include/net/flow.h | 9 +++++----
net/core/flow.c | 4 ++--
net/dccp/ipv6.c | 10 +++++-----
net/decnet/dn_route.c | 6 +++---
net/ipv4/icmp.c | 4 ++--
net/ipv4/netfilter.c | 4 ++--
net/ipv4/route.c | 2 +-
net/ipv6/af_inet6.c | 2 +-
net/ipv6/datagram.c | 3 ++-
net/ipv6/icmp.c | 6 +++---
net/ipv6/inet6_connection_sock.c | 2 +-
net/ipv6/ip6_tunnel.c | 5 +++--
net/ipv6/mcast.c | 4 ++--
net/ipv6/ndisc.c | 4 ++--
net/ipv6/netfilter.c | 2 +-
net/ipv6/netfilter/ip6t_REJECT.c | 2 +-
net/ipv6/raw.c | 3 ++-
net/ipv6/syncookies.c | 2 +-
net/ipv6/tcp_ipv6.c | 11 ++++++-----
net/ipv6/udp.c | 3 ++-
net/xfrm/xfrm_policy.c | 38 ++++++++++++++++++++------------------
22 files changed, 75 insertions(+), 67 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index 6c77879..6be3b08 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -291,21 +291,21 @@ enum {
struct flowi;
#ifndef CONFIG_XFRM
-static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
- struct sock *sk, int flags)
+static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
+ struct flowi *fl, struct sock *sk, int flags)
{
return 0;
}
-static inline int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
- struct sock *sk, int flags)
+static inline int __xfrm_lookup(struct net *net, struct dst_entry ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 3 ++-
net/xfrm/xfrm_policy.c | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1dc4ff0..158848f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -992,12 +992,13 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir,
struct sk_buff *skb,
unsigned int family, int reverse)
{
+ struct net *net = dev_net(skb->dev);
int ndir = dir | (reverse ? XFRM_POLICY_MASK + 1 : 0);
if (sk && sk->sk_policy[XFRM_POLICY_IN])
return __xfrm_policy_check(sk, ndir, skb, family);
- return (!init_net.xfrm.policy_count[dir] && !skb->sp) ||
+ return (!net->xfrm.policy_count[dir] && !skb->sp) ||
(skb->dst->flags & DST_NOPOLICY) ||
__xfrm_policy_check(sk, ndir, skb, family);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7c88a25..8097c99 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1894,6 +1894,7 @@ static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp
int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
unsigned short family)
{
+ struct net *net = dev_net(skb->dev);
struct xfrm_policy *pol;
struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
int npols = 0;
@@ -1938,7 +1939,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
if (!pol)
- pol = flow_cache_lookup(&init_net, &fl, family, fl_dir,
+ pol = flow_cache_lookup(net, &fl, family, fl_dir,
xfrm_policy_lookup);
if (IS_ERR(pol)) {
@@ -1961,7 +1962,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
npols ++;
#ifdef CONFIG_XFRM_SUB_POLICY
if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) {
- pols[1] = xfrm_policy_lookup_bytype(&init_net, XFRM_POLICY_TYPE_MAIN,
+ pols[1] = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN,
&fl, family,
...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 4 +++-
net/xfrm/xfrm_policy.c | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 158848f..36c8cff 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1050,7 +1050,9 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
- return !init_net.xfrm.policy_count[XFRM_POLICY_OUT] ||
+ struct net *net = dev_net(skb->dev);
+
+ return !net->xfrm.policy_count[XFRM_POLICY_OUT] ||
(skb->dst->flags & DST_NOXFRM) ||
__xfrm_route_forward(skb, family);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8097c99..54b50a2 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2044,6 +2044,7 @@ EXPORT_SYMBOL(__xfrm_policy_check);
int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
+ struct net *net = dev_net(skb->dev);
struct flowi fl;
if (xfrm_decode_session(skb, &fl, family) < 0) {
@@ -2052,7 +2053,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
return 0;
}
- return xfrm_lookup(&init_net, &skb->dst, &fl, NULL, 0) == 0;
+ return xfrm_lookup(net, &skb->dst, &fl, NULL, 0) == 0;
}
EXPORT_SYMBOL(__xfrm_route_forward);
--
1.5.6.5
--
Allow netdevice notifier as result.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_policy.c | 19 ++++++++-----------
1 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 54b50a2..49e0898 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2137,7 +2137,7 @@ static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_ent
write_unlock(&pol->lock);
}
-static void xfrm_prune_bundles(int (*func)(struct dst_entry *))
+static void xfrm_prune_bundles(struct net *net, int (*func)(struct dst_entry *))
{
struct dst_entry *gc_list = NULL;
int dir;
@@ -2150,11 +2150,11 @@ static void xfrm_prune_bundles(int (*func)(struct dst_entry *))
int i;
hlist_for_each_entry(pol, entry,
- &init_net.xfrm.policy_inexact[dir], bydst)
+ &net->xfrm.policy_inexact[dir], bydst)
prune_one_bundle(pol, func, &gc_list);
- table = init_net.xfrm.policy_bydst[dir].table;
- for (i = init_net.xfrm.policy_bydst[dir].hmask; i >= 0; i--) {
+ table = net->xfrm.policy_bydst[dir].table;
+ for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) {
hlist_for_each_entry(pol, entry, table + i, bydst)
prune_one_bundle(pol, func, &gc_list);
}
@@ -2175,12 +2175,12 @@ static int unused_bundle(struct dst_entry *dst)
static void __xfrm_garbage_collect(void)
{
- xfrm_prune_bundles(unused_bundle);
+ xfrm_prune_bundles(&init_net, unused_bundle);
}
-static int xfrm_flush_bundles(void)
+static int xfrm_flush_bundles(struct net *net)
{
- xfrm_prune_bundles(stale_bundle);
+ xfrm_prune_bundles(net, stale_bundle);
return 0;
}
@@ -2366,12 +2366,9 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void
{
struct net_device *dev = ptr;
- if (!net_eq(dev_net(dev), &init_net))
- return NOTIFY_DONE;
-
switch (event) {
case ...Pass netns pointer to struct xfrm_policy_afinfo::garbage_collect()
[This needs more thoughts on what to do with dst_ops]
[Currently stub to init_net]
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/xfrm6_policy.c | 2 +-
net/xfrm/xfrm_policy.c | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 36c8cff..bd25150 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -265,7 +265,7 @@ struct xfrm_dst;
struct xfrm_policy_afinfo {
unsigned short family;
struct dst_ops *dst_ops;
- void (*garbage_collect)(void);
+ void (*garbage_collect)(struct net *net);
struct dst_entry *(*dst_lookup)(int tos, xfrm_address_t *saddr,
xfrm_address_t *daddr);
int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 84dbb5a..a881ca3 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -187,7 +187,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
static inline int xfrm4_garbage_collect(struct dst_ops *ops)
{
- xfrm4_policy_afinfo.garbage_collect();
+ xfrm4_policy_afinfo.garbage_collect(&init_net);
return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 3b67ce7..2df8a78 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -220,7 +220,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
static inline int xfrm6_garbage_collect(struct dst_ops *ops)
{
- xfrm6_policy_afinfo.garbage_collect();
+ xfrm6_policy_afinfo.garbage_collect(&init_net);
return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 49e0898..7ebbdd6 100644
--- ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_input.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index c08a93e..a714dce 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -104,6 +104,7 @@ EXPORT_SYMBOL(xfrm_prepare_input);
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
{
+ struct net *net = dev_net(skb->dev);
int err;
__be32 seq;
struct xfrm_state *x;
@@ -151,7 +152,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop;
}
- x = xfrm_state_lookup(&init_net, daddr, spi, nexthdr, family);
+ x = xfrm_state_lookup(net, daddr, spi, nexthdr, family);
if (x == NULL) {
XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
xfrm_audit_state_notfound(skb, family, spi, seq);
--
1.5.6.5
--
Stub senders to init_net's one temporarily.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/xfrm.h | 2 +
include/net/xfrm.h | 7 ++-
net/xfrm/xfrm_output.c | 3 +-
net/xfrm/xfrm_state.c | 7 +--
net/xfrm/xfrm_user.c | 108 +++++++++++++++++++++++++++++++---------------
5 files changed, 83 insertions(+), 44 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index c53d173..09f3060 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -39,6 +39,8 @@ struct netns_xfrm {
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
unsigned int policy_count[XFRM_POLICY_MAX * 2];
struct work_struct policy_hash_work;
+
+ struct sock *nlsk;
};
#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bd25150..e027179 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -48,7 +48,6 @@ DECLARE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
#define XFRM_INC_STATS_USER(field)
#endif
-extern struct sock *xfrm_nl;
extern u32 sysctl_xfrm_aevent_etime;
extern u32 sysctl_xfrm_aevent_rseqth;
extern int sysctl_xfrm_larval_drop;
@@ -1516,18 +1515,20 @@ static inline int xfrm_policy_id2dir(u32 index)
return index & 7;
}
-static inline int xfrm_aevent_is_on(void)
+#ifdef CONFIG_XFRM
+static inline int xfrm_aevent_is_on(struct net *net)
{
struct sock *nlsk;
int ret = 0;
rcu_read_lock();
- nlsk = rcu_dereference(xfrm_nl);
+ nlsk = rcu_dereference(net->xfrm.nlsk);
if (nlsk)
ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS);
rcu_read_unlock();
return ret;
}
+#endif
static inline int xfrm_alg_len(struct xfrm_algo *alg)
{
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index dc50f1e..ba90e5e 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -41,6 +41,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = ...Grab netns either from netlink socket, state or policy.
SA and SPD flush are in init_net for now, this requires little
attention, see below.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_user.c | 76 +++++++++++++++++++++++++++++--------------------
1 files changed, 45 insertions(+), 31 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8b5b01d..ab8b138 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -316,11 +316,12 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
x->replay_maxdiff = nla_get_u32(rt);
}
-static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
+static struct xfrm_state *xfrm_state_construct(struct net *net,
+ struct xfrm_usersa_info *p,
struct nlattr **attrs,
int *errp)
{
- struct xfrm_state *x = xfrm_state_alloc(&init_net);
+ struct xfrm_state *x = xfrm_state_alloc(net);
int err = -ENOMEM;
if (!x)
@@ -391,6 +392,7 @@ error_no_put:
static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs)
{
+ struct net *net = sock_net(skb->sk);
struct xfrm_usersa_info *p = nlmsg_data(nlh);
struct xfrm_state *x;
int err;
@@ -403,7 +405,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err)
return err;
- x = xfrm_state_construct(p, attrs, &err);
+ x = xfrm_state_construct(net, p, attrs, &err);
if (!x)
return err;
@@ -431,7 +433,8 @@ out:
return err;
}
-static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
+static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
+ struct xfrm_usersa_id *p,
struct nlattr **attrs,
int *errp)
{
@@ -440,7 +443,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p,
if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) {
err = -ESRCH;
- x = xfrm_state_lookup(&init_net, &p->daddr, p->spi, ...SA and SPD flush are executed with NULL SA and SPD respectively, for these cases pass netns explicitly from userspace socket. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> --- include/net/xfrm.h | 1 + net/key/af_key.c | 2 ++ net/xfrm/xfrm_user.c | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e027179..52e784f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -256,6 +256,7 @@ struct km_event u32 seq; u32 pid; u32 event; + struct net *net; }; struct net_device; diff --git a/net/key/af_key.c b/net/key/af_key.c index a0d8498..ea7755a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1739,6 +1739,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; c.event = XFRM_MSG_FLUSHSA; + c.net = &init_net; km_state_notify(NULL, &c); return 0; @@ -2693,6 +2694,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; c.seq = hdr->sadb_msg_seq; + c.net = &init_net; km_policy_notify(NULL, 0, &c); return 0; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ab8b138..3e32ec2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1418,6 +1418,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; + c.net = net; km_state_notify(NULL, &c); return 0; @@ -1569,6 +1570,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; + c.net = net; km_policy_notify(NULL, 0, &c); return 0; } @@ -2084,7 +2086,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) static int xfrm_notify_sa_flush(struct ...
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 4 ++--
net/ipv6/mip6.c | 3 ++-
net/xfrm/xfrm_state.c | 4 ++--
net/xfrm/xfrm_user.c | 5 ++---
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 52e784f..f3ea160 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -552,7 +552,7 @@ struct xfrm_mgr
struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
- int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+ int (*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k);
};
@@ -1471,7 +1471,7 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
-extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
extern void xfrm_input_init(void);
extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 31295c8..f995e19 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -205,6 +205,7 @@ static inline int mip6_report_rl_allow(struct timeval *stamp,
static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
{
+ struct net *net = xs_net(x);
struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
struct ipv6_destopt_hao *hao = NULL;
struct ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 3 ++-
net/ipv4/xfrm4_policy.c | 7 ++++---
net/ipv6/xfrm6_policy.c | 7 ++++---
net/xfrm/xfrm_policy.c | 7 ++++---
4 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f3ea160..b16d4c0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -266,7 +266,8 @@ struct xfrm_policy_afinfo {
unsigned short family;
struct dst_ops *dst_ops;
void (*garbage_collect)(struct net *net);
- struct dst_entry *(*dst_lookup)(int tos, xfrm_address_t *saddr,
+ struct dst_entry *(*dst_lookup)(struct net *net, int tos,
+ xfrm_address_t *saddr,
xfrm_address_t *daddr);
int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);
struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index a881ca3..e1cf9ed 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -18,7 +18,8 @@
static struct dst_ops xfrm4_dst_ops;
static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
-static struct dst_entry *xfrm4_dst_lookup(int tos, xfrm_address_t *saddr,
+static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
+ xfrm_address_t *saddr,
xfrm_address_t *daddr)
{
struct flowi fl = {
@@ -36,7 +37,7 @@ static struct dst_entry *xfrm4_dst_lookup(int tos, xfrm_address_t *saddr,
if (saddr)
fl.fl4_src = saddr->a4;
- err = __ip_route_output_key(&init_net, &rt, &fl);
+ err = __ip_route_output_key(net, &rt, &fl);
dst = &rt->u.dst;
if (err)
dst = ERR_PTR(err);
@@ -48,7 +49,7 @@ static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
struct dst_entry *dst;
struct rtable *rt;
- dst = xfrm4_dst_lookup(0, NULL, daddr);
+ dst = xfrm4_dst_lookup(&init_net, 0, NULL, daddr);
if (IS_ERR(dst))
return -EHOSTUNREACH;
diff --git ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 2 +-
net/ipv4/xfrm4_policy.c | 5 +++--
net/ipv6/xfrm6_policy.c | 5 +++--
net/xfrm/xfrm_policy.c | 7 ++++---
4 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index b16d4c0..d076f3d 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -269,7 +269,7 @@ struct xfrm_policy_afinfo {
struct dst_entry *(*dst_lookup)(struct net *net, int tos,
xfrm_address_t *saddr,
xfrm_address_t *daddr);
- int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);
+ int (*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);
void (*decode_session)(struct sk_buff *skb,
struct flowi *fl,
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index e1cf9ed..2ad24ba 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -44,12 +44,13 @@ static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
return dst;
}
-static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
+static int xfrm4_get_saddr(struct net *net,
+ xfrm_address_t *saddr, xfrm_address_t *daddr)
{
struct dst_entry *dst;
struct rtable *rt;
- dst = xfrm4_dst_lookup(&init_net, 0, NULL, daddr);
+ dst = xfrm4_dst_lookup(net, 0, NULL, daddr);
if (IS_ERR(dst))
return -EHOSTUNREACH;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index d7a5b8b..97ab068 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -50,12 +50,13 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
return dst;
}
-static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr)
+static int xfrm6_get_saddr(struct net *net,
+ xfrm_address_t *saddr, xfrm_address_t *daddr)
{
struct dst_entry *dst;
struct ...SA/SPD doesn't pin netns (and it shouldn't), so get rid of them by hand.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/xfrm/xfrm_policy.c | 14 ++++++++++++++
net/xfrm/xfrm_state.c | 8 ++++++++
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7c7bb54..fcf8c92 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2441,9 +2441,23 @@ out_byidx:
static void xfrm_policy_fini(struct net *net)
{
+ struct xfrm_audit audit_info;
unsigned int sz;
int dir;
+ flush_work(&net->xfrm.policy_hash_work);
+#ifdef CONFIG_XFRM_SUB_POLICY
+ audit_info.loginuid = -1;
+ audit_info.sessionid = -1;
+ audit_info.secid = 0;
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info);
+#endif
+ audit_info.loginuid = -1;
+ audit_info.sessionid = -1;
+ audit_info.secid = 0;
+ xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info);
+ flush_work(&xfrm_policy_gc_work);
+
WARN_ON(!list_empty(&net->xfrm.policy_all));
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d594b5a..662e47b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2114,8 +2114,16 @@ out_bydst:
void xfrm_state_fini(struct net *net)
{
+ struct xfrm_audit audit_info;
unsigned int sz;
+ flush_work(&net->xfrm.state_hash_work);
+ audit_info.loginuid = -1;
+ audit_info.sessionid = -1;
+ audit_info.secid = 0;
+ xfrm_state_flush(net, IPSEC_PROTO_ANY, &audit_info);
+ flush_work(&net->xfrm.state_gc_work);
+
WARN_ON(!list_empty(&net->xfrm.state_all));
sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head);
--
1.5.6.5
--
* netns boilerplate
* keep per-netns socket list
* keep per-netns number of sockets
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/key/af_key.c | 88 ++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ea7755a..e80b264 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -27,6 +27,7 @@
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <net/net_namespace.h>
+#include <net/netns/generic.h>
#include <net/xfrm.h>
#include <net/sock.h>
@@ -34,15 +35,16 @@
#define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
#define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
-
-/* List of all pfkey sockets. */
-static HLIST_HEAD(pfkey_table);
+static int pfkey_net_id;
+struct netns_pfkey {
+ /* List of all pfkey sockets. */
+ struct hlist_head table;
+ atomic_t socks_nr;
+};
static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait);
static DEFINE_RWLOCK(pfkey_table_lock);
static atomic_t pfkey_table_users = ATOMIC_INIT(0);
-static atomic_t pfkey_socks_nr = ATOMIC_INIT(0);
-
struct pfkey_sock {
/* struct sock must be the first member of struct pfkey_sock */
struct sock sk;
@@ -89,6 +91,9 @@ static void pfkey_terminate_dump(struct pfkey_sock *pfk)
static void pfkey_sock_destruct(struct sock *sk)
{
+ struct net *net = sock_net(sk);
+ struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
+
pfkey_terminate_dump(pfkey_sk(sk));
skb_queue_purge(&sk->sk_receive_queue);
@@ -100,7 +105,7 @@ static void pfkey_sock_destruct(struct sock *sk)
WARN_ON(atomic_read(&sk->sk_rmem_alloc));
WARN_ON(atomic_read(&sk->sk_wmem_alloc));
- atomic_dec(&pfkey_socks_nr);
+ atomic_dec(&net_pfkey->socks_nr);
}
static void pfkey_table_grab(void)
@@ -151,8 +156,11 @@ static const struct proto_ops pfkey_ops;
static void pfkey_insert(struct sock *sk)
{
+ struct net *net = sock_net(sk);
+ struct netns_pfkey *net_pfkey = ...* interaction with userspace -- take netns from userspace socket.
* in ->notify hook take netns either from SA or explicitly passed --
we don't know if SA/SPD flush is coming.
* stub policy migration with init_net for now.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/key/af_key.c | 105 +++++++++++++++++++++++++++++++-----------------------
1 files changed, 60 insertions(+), 45 deletions(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e80b264..bb78ef9 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -261,9 +261,9 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
#define BROADCAST_REGISTERED 2
#define BROADCAST_PROMISC_ONLY 4
static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
- int broadcast_flags, struct sock *one_sk)
+ int broadcast_flags, struct sock *one_sk,
+ struct net *net)
{
- struct net *net = &init_net;
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
struct sock *sk;
struct hlist_node *node;
@@ -336,7 +336,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
hdr->sadb_msg_seq = 0;
hdr->sadb_msg_errno = rc;
pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
- &pfk->sk);
+ &pfk->sk, sock_net(&pfk->sk));
pfk->dump.skb = NULL;
}
@@ -375,7 +375,7 @@ static int pfkey_error(struct sadb_msg *orig, int err, struct sock *sk)
hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
sizeof(uint64_t));
- pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk);
+ pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
return 0;
}
@@ -653,7 +653,7 @@ int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr)
xaddr);
}
-static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs)
+static struct xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_msg *hdr, void **ext_hdrs)
{
struct sadb_sa *sa;
struct sadb_address ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/key/af_key.c | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index bb78ef9..f8bd8df 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3673,7 +3673,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
{
- struct net *net = &init_net;
+ struct net *net = seq_file_net(f);
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
struct sock *s;
struct hlist_node *node;
@@ -3692,7 +3692,7 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
{
- struct net *net = &init_net;
+ struct net *net = seq_file_net(f);
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
++*ppos;
@@ -3715,38 +3715,39 @@ static struct seq_operations pfkey_seq_ops = {
static int pfkey_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &pfkey_seq_ops);
+ return seq_open_net(inode, file, &pfkey_seq_ops,
+ sizeof(struct seq_net_private));
}
static struct file_operations pfkey_proc_ops = {
.open = pfkey_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_net,
};
-static int pfkey_init_proc(void)
+static int __net_init pfkey_init_proc(struct net *net)
{
struct proc_dir_entry *e;
- e = proc_net_fops_create(&init_net, "pfkey", 0, &pfkey_proc_ops);
+ e = proc_net_fops_create(net, "pfkey", 0, &pfkey_proc_ops);
if (e == NULL)
return -ENOMEM;
return 0;
}
-static void pfkey_exit_proc(void)
+static void pfkey_exit_proc(struct net *net)
{
- proc_net_remove(&init_net, "pfkey");
+ proc_net_remove(net, "pfkey");
}
#else
-static inline int pfkey_init_proc(void)
+static int __net_init pfkey_init_proc(struct net *net)
{
return ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
net/ipv4/ah4.c | 4 +++-
net/ipv4/esp4.c | 4 +++-
net/ipv6/ah6.c | 3 ++-
net/ipv6/esp6.c | 3 ++-
4 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 750426b..e878e49 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -201,6 +201,7 @@ out:
static void ah4_err(struct sk_buff *skb, u32 info)
{
+ struct net *net = dev_net(skb->dev);
struct iphdr *iph = (struct iphdr *)skb->data;
struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2));
struct xfrm_state *x;
@@ -209,7 +210,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
return;
- x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
+ x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET);
if (!x)
return;
printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n",
@@ -314,6 +315,7 @@ static struct net_protocol ah4_protocol = {
.handler = xfrm4_rcv,
.err_handler = ah4_err,
.no_policy = 1,
+ .netns_ok = 1,
};
static int __init ah4_init(void)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 3595012..18bb383 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -413,6 +413,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
static void esp4_err(struct sk_buff *skb, u32 info)
{
+ struct net *net = dev_net(skb->dev);
struct iphdr *iph = (struct iphdr *)skb->data;
struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
struct xfrm_state *x;
@@ -421,7 +422,7 @@ static void esp4_err(struct sk_buff *skb, u32 info)
icmp_hdr(skb)->code != ICMP_FRAG_NEEDED)
return;
- x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
+ x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET);
if (!x)
return;
...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/netns/mib.h | 3 ++
include/net/xfrm.h | 13 +++----
net/ipv6/xfrm6_input.c | 9 +++--
net/xfrm/xfrm_input.c | 22 ++++++------
net/xfrm/xfrm_output.c | 15 ++++----
net/xfrm/xfrm_policy.c | 82 +++++++++++++++++++++++++++--------------------
net/xfrm/xfrm_proc.c | 2 +-
7 files changed, 81 insertions(+), 65 deletions(-)
diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h
index 10cb7c3..0b44112 100644
--- a/include/net/netns/mib.h
+++ b/include/net/netns/mib.h
@@ -20,6 +20,9 @@ struct netns_mib {
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
#endif
+#ifdef CONFIG_XFRM_STATISTICS
+ DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
+#endif
};
#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d076f3d..78ec3e8 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -38,14 +38,13 @@
MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
#ifdef CONFIG_XFRM_STATISTICS
-DECLARE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
-#define XFRM_INC_STATS(field) SNMP_INC_STATS(xfrm_statistics, field)
-#define XFRM_INC_STATS_BH(field) SNMP_INC_STATS_BH(xfrm_statistics, field)
-#define XFRM_INC_STATS_USER(field) SNMP_INC_STATS_USER(xfrm_statistics, field)
+#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
+#define XFRM_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.xfrm_statistics, field)
+#define XFRM_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)-mib.xfrm_statistics, field)
#else
-#define XFRM_INC_STATS(field)
-#define XFRM_INC_STATS_BH(field)
-#define XFRM_INC_STATS_USER(field)
+#define XFRM_INC_STATS(net, field) ((void)(net))
+#define XFRM_INC_STATS_BH(net, field) ((void)(net))
+#define XFRM_INC_STATS_USER(net, field) ((void)(net))
#endif
extern u32 sysctl_xfrm_aevent_etime;
diff ...Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/xfrm.h | 3 ++-
net/xfrm/xfrm_policy.c | 11 +++++++----
net/xfrm/xfrm_proc.c | 26 ++++++++++++--------------
3 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 78ec3e8..1554ccd 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1306,7 +1306,8 @@ static inline void xfrm6_fini(void)
#endif
#ifdef CONFIG_XFRM_STATISTICS
-extern int xfrm_proc_init(void);
+extern int xfrm_proc_init(struct net *net);
+extern void xfrm_proc_fini(struct net *net);
#endif
extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e239a25..38822b3 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2377,14 +2377,20 @@ static struct notifier_block xfrm_dev_notifier = {
#ifdef CONFIG_XFRM_STATISTICS
static int __net_init xfrm_statistics_init(struct net *net)
{
+ int rv;
+
if (snmp_mib_init((void **)net->mib.xfrm_statistics,
sizeof(struct linux_xfrm_mib)) < 0)
return -ENOMEM;
- return 0;
+ rv = xfrm_proc_init(net);
+ if (rv < 0)
+ snmp_mib_free((void **)net->mib.xfrm_statistics);
+ return rv;
}
static void xfrm_statistics_fini(struct net *net)
{
+ xfrm_proc_fini(net);
snmp_mib_free((void **)net->mib.xfrm_statistics);
}
#else
@@ -2524,9 +2530,6 @@ void __init xfrm_init(void)
{
register_pernet_subsys(&xfrm_net_ops);
xfrm_input_init();
-#ifdef CONFIG_XFRM_STATISTICS
- xfrm_proc_init();
-#endif
}
#ifdef CONFIG_AUDITSYSCALL
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c
index 27a2ab9..284eaef 100644
--- a/net/xfrm/xfrm_proc.c
+++ b/net/xfrm/xfrm_proc.c
@@ -59,17 +59,18 @@ fold_field(void *mib[], int offt)
static int xfrm_statistics_seq_show(struct seq_file *seq, void *v)
{
+ struct net *net = seq->private;
int i;
for (i=0; xfrm_mib_list[i].name; i++)
seq_printf(seq, ...Make
net.core.xfrm_aevent_etime
net.core.xfrm_acq_expires
net.core.xfrm_aevent_rseqth
net.core.xfrm_larval_drop
sysctls per-netns.
For that make net_core_path[] global, register it to prevent two
/proc/net/core antries and change initcall position -- xfrm_init() is called
from fs_initcall, so this one should be fs_initcall at least.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/net/ip.h | 1 +
include/net/netns/xfrm.h | 10 +++++
include/net/xfrm.h | 14 +++++---
net/core/sysctl_net_core.c | 42 +++-------------------
net/xfrm/Makefile | 4 +-
net/xfrm/xfrm_policy.c | 10 ++++--
net/xfrm/xfrm_state.c | 16 ++------
net/xfrm/xfrm_sysctl.c | 85 ++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_user.c | 4 +-
9 files changed, 125 insertions(+), 61 deletions(-)
create mode 100644 net/xfrm/xfrm_sysctl.c
diff --git a/include/net/ip.h b/include/net/ip.h
index bc026ec..406f523 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -187,6 +187,7 @@ extern void inet_get_local_port_range(int *low, int *high);
extern int sysctl_ip_default_ttl;
extern int sysctl_ip_nonlocal_bind;
+extern struct ctl_path net_core_path[];
extern struct ctl_path net_ipv4_ctl_path[];
/* From inetpeer.c */
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 09f3060..1ba9127 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -6,6 +6,8 @@
#include <linux/workqueue.h>
#include <linux/xfrm.h>
+struct ctl_table_header;
+
struct xfrm_policy_hash {
struct hlist_head *table;
unsigned int hmask;
@@ -41,6 +43,14 @@ struct netns_xfrm {
struct work_struct policy_hash_work;
struct sock *nlsk;
+
+ u32 sysctl_aevent_etime;
+ u32 sysctl_aevent_rseqth;
+ int sysctl_larval_drop;
+ u32 sysctl_acq_expires;
+#ifdef CONFIG_SYSCTL
+ struct ctl_table_header *sysctl_hdr;
+#endif
};
#endif
diff --git a/include/net/xfrm.h ...From: Alexey Dobriyan <adobriyan@gmail.com> Applied. Thanks a lot Alexey. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Yahoo! Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied, thanks. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> ^^^^^^^^ Applied, thanks. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Look mom, no ifdefs! Amazing! --
There're gone and won't return, honey. In fact, I don't like pnet only a little now and thinking about: net = read_net(foo->foo_net); write_net(foo->foo_net, net); --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
From: Alexey Dobriyan <adobriyan@gmail.com> Applied. --
