| .. | .. |
|---|
| 77 | 77 | #include <linux/string.h> |
|---|
| 78 | 78 | #include <linux/netfilter_ipv4.h> |
|---|
| 79 | 79 | #include <linux/slab.h> |
|---|
| 80 | +#include <linux/locallock.h> |
|---|
| 80 | 81 | #include <net/snmp.h> |
|---|
| 81 | 82 | #include <net/ip.h> |
|---|
| 82 | 83 | #include <net/route.h> |
|---|
| .. | .. |
|---|
| 204 | 205 | * |
|---|
| 205 | 206 | * On SMP we have one ICMP socket per-cpu. |
|---|
| 206 | 207 | */ |
|---|
| 208 | +static DEFINE_LOCAL_IRQ_LOCK(icmp_sk_lock); |
|---|
| 209 | + |
|---|
| 207 | 210 | static struct sock *icmp_sk(struct net *net) |
|---|
| 208 | 211 | { |
|---|
| 209 | 212 | return *this_cpu_ptr(net->ipv4.icmp_sk); |
|---|
| .. | .. |
|---|
| 214 | 217 | { |
|---|
| 215 | 218 | struct sock *sk; |
|---|
| 216 | 219 | |
|---|
| 220 | + if (!local_trylock(icmp_sk_lock)) |
|---|
| 221 | + return NULL; |
|---|
| 222 | + |
|---|
| 217 | 223 | sk = icmp_sk(net); |
|---|
| 218 | 224 | |
|---|
| 219 | 225 | if (unlikely(!spin_trylock(&sk->sk_lock.slock))) { |
|---|
| 220 | 226 | /* This can happen if the output path signals a |
|---|
| 221 | 227 | * dst_link_failure() for an outgoing ICMP packet. |
|---|
| 222 | 228 | */ |
|---|
| 229 | + local_unlock(icmp_sk_lock); |
|---|
| 223 | 230 | return NULL; |
|---|
| 224 | 231 | } |
|---|
| 225 | 232 | return sk; |
|---|
| .. | .. |
|---|
| 228 | 235 | static inline void icmp_xmit_unlock(struct sock *sk) |
|---|
| 229 | 236 | { |
|---|
| 230 | 237 | spin_unlock(&sk->sk_lock.slock); |
|---|
| 238 | + local_unlock(icmp_sk_lock); |
|---|
| 231 | 239 | } |
|---|
| 232 | 240 | |
|---|
| 233 | 241 | int sysctl_icmp_msgs_per_sec __read_mostly = 1000; |
|---|