[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: Denis V. Lunev <den@openvz.org> Acked-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5c8cafd65e
commit
4a6ad7a141
2 changed files with 34 additions and 17 deletions
|
@ -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];
|
||||||
*
|
*
|
||||||
* 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,
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
.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)
|
||||||
__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] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue