Commit 4a6ad7a1 authored by Denis V. Lunev's avatar Denis V. Lunev Committed by David S. Miller

[NETNS]: Make icmp_sk per namespace.

All preparations are done. Now just add a hook to perform an
initialization on namespace startup and replace icmp_sk macro with
proper inline call.
Signed-off-by: default avatarDenis V. Lunev <den@openvz.org>
Acked-by: default avatarDaniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5c8cafd6
...@@ -26,6 +26,8 @@ struct netns_ipv4 { ...@@ -26,6 +26,8 @@ struct netns_ipv4 {
struct hlist_head *fib_table_hash; struct hlist_head *fib_table_hash;
struct sock *fibnl; struct sock *fibnl;
struct sock **icmp_sk;
struct netns_frags frags; struct netns_frags frags;
#ifdef CONFIG_NETFILTER #ifdef CONFIG_NETFILTER
struct xt_table *iptable_filter; struct xt_table *iptable_filter;
......
...@@ -229,8 +229,10 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1]; ...@@ -229,8 +229,10 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
* *
* On SMP we have one ICMP socket per-cpu. * On SMP we have one ICMP socket per-cpu.
*/ */
static struct sock **__icmp_sk = NULL; static struct sock *icmp_sk(struct net *net)
#define icmp_sk (__icmp_sk[smp_processor_id()]) {
return net->ipv4.icmp_sk[smp_processor_id()];
}
static inline int icmp_xmit_lock(struct sock *sk) static inline int icmp_xmit_lock(struct sock *sk)
{ {
...@@ -349,7 +351,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, ...@@ -349,7 +351,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
struct sock *sk; struct sock *sk;
struct sk_buff *skb; struct sk_buff *skb;
sk = icmp_sk; sk = icmp_sk(rt->u.dst.dev->nd_net);
if (ip_append_data(sk, icmp_glue_bits, icmp_param, if (ip_append_data(sk, icmp_glue_bits, icmp_param,
icmp_param->data_len+icmp_param->head_len, icmp_param->data_len+icmp_param->head_len,
icmp_param->head_len, icmp_param->head_len,
...@@ -378,10 +380,11 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, ...@@ -378,10 +380,11 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
{ {
struct sock *sk = icmp_sk;
struct inet_sock *inet = inet_sk(sk);
struct ipcm_cookie ipc; struct ipcm_cookie ipc;
struct rtable *rt = (struct rtable *)skb->dst; struct rtable *rt = (struct rtable *)skb->dst;
struct net *net = rt->u.dst.dev->nd_net;
struct sock *sk = icmp_sk(net);
struct inet_sock *inet = inet_sk(sk);
__be32 daddr; __be32 daddr;
if (ip_options_echo(&icmp_param->replyopts, skb)) if (ip_options_echo(&icmp_param->replyopts, skb))
...@@ -407,7 +410,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) ...@@ -407,7 +410,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
.tos = RT_TOS(ip_hdr(skb)->tos) } }, .tos = RT_TOS(ip_hdr(skb)->tos) } },
.proto = IPPROTO_ICMP }; .proto = IPPROTO_ICMP };
security_skb_classify_flow(skb, &fl); security_skb_classify_flow(skb, &fl);
if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl)) if (ip_route_output_key(net, &rt, &fl))
goto out_unlock; goto out_unlock;
} }
if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
...@@ -440,11 +443,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) ...@@ -440,11 +443,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
__be32 saddr; __be32 saddr;
u8 tos; u8 tos;
struct net *net; struct net *net;
struct sock *sk = icmp_sk; struct sock *sk;
if (!rt) if (!rt)
goto out; goto out;
net = rt->u.dst.dev->nd_net; net = rt->u.dst.dev->nd_net;
sk = icmp_sk(net);
/* /*
* Find the original header. It is expected to be valid, of course. * Find the original header. It is expected to be valid, of course.
...@@ -1142,22 +1146,23 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { ...@@ -1142,22 +1146,23 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
}, },
}; };
static void __exit icmp_exit(void) static void __net_exit icmp_sk_exit(struct net *net)
{ {
int i; int i;
for_each_possible_cpu(i) for_each_possible_cpu(i)
sk_release_kernel(__icmp_sk[i]); sk_release_kernel(net->ipv4.icmp_sk[i]);
kfree(__icmp_sk); kfree(net->ipv4.icmp_sk);
__icmp_sk = NULL; net->ipv4.icmp_sk = NULL;
} }
int __init icmp_init(void) int __net_init icmp_sk_init(struct net *net)
{ {
int i, err; int i, err;
__icmp_sk = kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); net->ipv4.icmp_sk =
if (__icmp_sk == NULL) kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
if (net->ipv4.icmp_sk == NULL)
return -ENOMEM; return -ENOMEM;
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
...@@ -1169,8 +1174,8 @@ int __init icmp_init(void) ...@@ -1169,8 +1174,8 @@ int __init icmp_init(void)
if (err < 0) if (err < 0)
goto fail; goto fail;
__icmp_sk[i] = sk = sock->sk; net->ipv4.icmp_sk[i] = sk = sock->sk;
sk_change_net(sk, &init_net); sk_change_net(sk, net);
sk->sk_allocation = GFP_ATOMIC; sk->sk_allocation = GFP_ATOMIC;
...@@ -1193,10 +1198,20 @@ int __init icmp_init(void) ...@@ -1193,10 +1198,20 @@ int __init icmp_init(void)
return 0; return 0;
fail: fail:
icmp_exit(); icmp_sk_exit(net);
return err; return err;
} }
static struct pernet_operations __net_initdata icmp_sk_ops = {
.init = icmp_sk_init,
.exit = icmp_sk_exit,
};
int __init icmp_init(void)
{
return register_pernet_device(&icmp_sk_ops);
}
EXPORT_SYMBOL(icmp_err_convert); EXPORT_SYMBOL(icmp_err_convert);
EXPORT_SYMBOL(icmp_send); EXPORT_SYMBOL(icmp_send);
EXPORT_SYMBOL(icmp_statistics); EXPORT_SYMBOL(icmp_statistics);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment