diff options
author | David S. Miller <davem@davemloft.net> | 2015-06-08 23:06:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-08 23:06:56 -0400 |
commit | 941742f49762ba4c908510f036b09a46c1b14513 (patch) | |
tree | aafb7a72c2072f98889406668003234bed56df02 /net/ipv6 | |
parent | ac7ba51c215db5739eb640f2f26025ced8668285 (diff) | |
parent | 5879ae5fd052a63d5ac0684320cb7df3e83da7de (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf_core.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 8 |
2 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index d873ceea86e6..ca09bf49ac68 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
@@ -133,6 +133,14 @@ static void snmp6_free_dev(struct inet6_dev *idev) | |||
133 | free_percpu(idev->stats.ipv6); | 133 | free_percpu(idev->stats.ipv6); |
134 | } | 134 | } |
135 | 135 | ||
136 | static void in6_dev_finish_destroy_rcu(struct rcu_head *head) | ||
137 | { | ||
138 | struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); | ||
139 | |||
140 | snmp6_free_dev(idev); | ||
141 | kfree(idev); | ||
142 | } | ||
143 | |||
136 | /* Nobody refers to this device, we may destroy it. */ | 144 | /* Nobody refers to this device, we may destroy it. */ |
137 | 145 | ||
138 | void in6_dev_finish_destroy(struct inet6_dev *idev) | 146 | void in6_dev_finish_destroy(struct inet6_dev *idev) |
@@ -151,7 +159,6 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
151 | pr_warn("Freeing alive inet6 device %p\n", idev); | 159 | pr_warn("Freeing alive inet6 device %p\n", idev); |
152 | return; | 160 | return; |
153 | } | 161 | } |
154 | snmp6_free_dev(idev); | 162 | call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); |
155 | kfree_rcu(idev, rcu); | ||
156 | } | 163 | } |
157 | EXPORT_SYMBOL(in6_dev_finish_destroy); | 164 | EXPORT_SYMBOL(in6_dev_finish_destroy); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index f2e464eba5ef..41a73da371a9 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -212,13 +212,13 @@ static int ip6_input_finish(struct sock *sk, struct sk_buff *skb) | |||
212 | */ | 212 | */ |
213 | 213 | ||
214 | rcu_read_lock(); | 214 | rcu_read_lock(); |
215 | resubmit: | ||
216 | idev = ip6_dst_idev(skb_dst(skb)); | 215 | idev = ip6_dst_idev(skb_dst(skb)); |
217 | if (!pskb_pull(skb, skb_transport_offset(skb))) | 216 | if (!pskb_pull(skb, skb_transport_offset(skb))) |
218 | goto discard; | 217 | goto discard; |
219 | nhoff = IP6CB(skb)->nhoff; | 218 | nhoff = IP6CB(skb)->nhoff; |
220 | nexthdr = skb_network_header(skb)[nhoff]; | 219 | nexthdr = skb_network_header(skb)[nhoff]; |
221 | 220 | ||
221 | resubmit: | ||
222 | raw = raw6_local_deliver(skb, nexthdr); | 222 | raw = raw6_local_deliver(skb, nexthdr); |
223 | ipprot = rcu_dereference(inet6_protos[nexthdr]); | 223 | ipprot = rcu_dereference(inet6_protos[nexthdr]); |
224 | if (ipprot) { | 224 | if (ipprot) { |
@@ -246,10 +246,12 @@ resubmit: | |||
246 | goto discard; | 246 | goto discard; |
247 | 247 | ||
248 | ret = ipprot->handler(skb); | 248 | ret = ipprot->handler(skb); |
249 | if (ret > 0) | 249 | if (ret < 0) { |
250 | nexthdr = -ret; | ||
250 | goto resubmit; | 251 | goto resubmit; |
251 | else if (ret == 0) | 252 | } else if (ret == 0) { |
252 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); | 253 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); |
254 | } | ||
253 | } else { | 255 | } else { |
254 | if (!raw) { | 256 | if (!raw) { |
255 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 257 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |