diff options
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r-- | net/core/neighbour.c | 488 |
1 files changed, 304 insertions, 184 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index a4e0a7482c2b..799f06e03a22 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -41,7 +41,6 @@ | |||
41 | 41 | ||
42 | #define NEIGH_PRINTK(x...) printk(x) | 42 | #define NEIGH_PRINTK(x...) printk(x) |
43 | #define NEIGH_NOPRINTK(x...) do { ; } while(0) | 43 | #define NEIGH_NOPRINTK(x...) do { ; } while(0) |
44 | #define NEIGH_PRINTK0 NEIGH_PRINTK | ||
45 | #define NEIGH_PRINTK1 NEIGH_NOPRINTK | 44 | #define NEIGH_PRINTK1 NEIGH_NOPRINTK |
46 | #define NEIGH_PRINTK2 NEIGH_NOPRINTK | 45 | #define NEIGH_PRINTK2 NEIGH_NOPRINTK |
47 | 46 | ||
@@ -122,7 +121,7 @@ static void neigh_cleanup_and_release(struct neighbour *neigh) | |||
122 | 121 | ||
123 | unsigned long neigh_rand_reach_time(unsigned long base) | 122 | unsigned long neigh_rand_reach_time(unsigned long base) |
124 | { | 123 | { |
125 | return (base ? (net_random() % base) + (base >> 1) : 0); | 124 | return base ? (net_random() % base) + (base >> 1) : 0; |
126 | } | 125 | } |
127 | EXPORT_SYMBOL(neigh_rand_reach_time); | 126 | EXPORT_SYMBOL(neigh_rand_reach_time); |
128 | 127 | ||
@@ -131,15 +130,20 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
131 | { | 130 | { |
132 | int shrunk = 0; | 131 | int shrunk = 0; |
133 | int i; | 132 | int i; |
133 | struct neigh_hash_table *nht; | ||
134 | 134 | ||
135 | NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs); | 135 | NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs); |
136 | 136 | ||
137 | write_lock_bh(&tbl->lock); | 137 | write_lock_bh(&tbl->lock); |
138 | for (i = 0; i <= tbl->hash_mask; i++) { | 138 | nht = rcu_dereference_protected(tbl->nht, |
139 | struct neighbour *n, **np; | 139 | lockdep_is_held(&tbl->lock)); |
140 | for (i = 0; i <= nht->hash_mask; i++) { | ||
141 | struct neighbour *n; | ||
142 | struct neighbour __rcu **np; | ||
140 | 143 | ||
141 | np = &tbl->hash_buckets[i]; | 144 | np = &nht->hash_buckets[i]; |
142 | while ((n = *np) != NULL) { | 145 | while ((n = rcu_dereference_protected(*np, |
146 | lockdep_is_held(&tbl->lock))) != NULL) { | ||
143 | /* Neighbour record may be discarded if: | 147 | /* Neighbour record may be discarded if: |
144 | * - nobody refers to it. | 148 | * - nobody refers to it. |
145 | * - it is not permanent | 149 | * - it is not permanent |
@@ -147,7 +151,9 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
147 | write_lock(&n->lock); | 151 | write_lock(&n->lock); |
148 | if (atomic_read(&n->refcnt) == 1 && | 152 | if (atomic_read(&n->refcnt) == 1 && |
149 | !(n->nud_state & NUD_PERMANENT)) { | 153 | !(n->nud_state & NUD_PERMANENT)) { |
150 | *np = n->next; | 154 | rcu_assign_pointer(*np, |
155 | rcu_dereference_protected(n->next, | ||
156 | lockdep_is_held(&tbl->lock))); | ||
151 | n->dead = 1; | 157 | n->dead = 1; |
152 | shrunk = 1; | 158 | shrunk = 1; |
153 | write_unlock(&n->lock); | 159 | write_unlock(&n->lock); |
@@ -199,16 +205,24 @@ static void pneigh_queue_purge(struct sk_buff_head *list) | |||
199 | static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | 205 | static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) |
200 | { | 206 | { |
201 | int i; | 207 | int i; |
208 | struct neigh_hash_table *nht; | ||
202 | 209 | ||
203 | for (i = 0; i <= tbl->hash_mask; i++) { | 210 | nht = rcu_dereference_protected(tbl->nht, |
204 | struct neighbour *n, **np = &tbl->hash_buckets[i]; | 211 | lockdep_is_held(&tbl->lock)); |
205 | 212 | ||
206 | while ((n = *np) != NULL) { | 213 | for (i = 0; i <= nht->hash_mask; i++) { |
214 | struct neighbour *n; | ||
215 | struct neighbour __rcu **np = &nht->hash_buckets[i]; | ||
216 | |||
217 | while ((n = rcu_dereference_protected(*np, | ||
218 | lockdep_is_held(&tbl->lock))) != NULL) { | ||
207 | if (dev && n->dev != dev) { | 219 | if (dev && n->dev != dev) { |
208 | np = &n->next; | 220 | np = &n->next; |
209 | continue; | 221 | continue; |
210 | } | 222 | } |
211 | *np = n->next; | 223 | rcu_assign_pointer(*np, |
224 | rcu_dereference_protected(n->next, | ||
225 | lockdep_is_held(&tbl->lock))); | ||
212 | write_lock(&n->lock); | 226 | write_lock(&n->lock); |
213 | neigh_del_timer(n); | 227 | neigh_del_timer(n); |
214 | n->dead = 1; | 228 | n->dead = 1; |
@@ -279,6 +293,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl) | |||
279 | 293 | ||
280 | skb_queue_head_init(&n->arp_queue); | 294 | skb_queue_head_init(&n->arp_queue); |
281 | rwlock_init(&n->lock); | 295 | rwlock_init(&n->lock); |
296 | seqlock_init(&n->ha_lock); | ||
282 | n->updated = n->used = now; | 297 | n->updated = n->used = now; |
283 | n->nud_state = NUD_NONE; | 298 | n->nud_state = NUD_NONE; |
284 | n->output = neigh_blackhole; | 299 | n->output = neigh_blackhole; |
@@ -297,64 +312,86 @@ out_entries: | |||
297 | goto out; | 312 | goto out; |
298 | } | 313 | } |
299 | 314 | ||
300 | static struct neighbour **neigh_hash_alloc(unsigned int entries) | 315 | static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries) |
301 | { | 316 | { |
302 | unsigned long size = entries * sizeof(struct neighbour *); | 317 | size_t size = entries * sizeof(struct neighbour *); |
303 | struct neighbour **ret; | 318 | struct neigh_hash_table *ret; |
319 | struct neighbour __rcu **buckets; | ||
304 | 320 | ||
305 | if (size <= PAGE_SIZE) { | 321 | ret = kmalloc(sizeof(*ret), GFP_ATOMIC); |
306 | ret = kzalloc(size, GFP_ATOMIC); | 322 | if (!ret) |
307 | } else { | 323 | return NULL; |
308 | ret = (struct neighbour **) | 324 | if (size <= PAGE_SIZE) |
309 | __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size)); | 325 | buckets = kzalloc(size, GFP_ATOMIC); |
326 | else | ||
327 | buckets = (struct neighbour __rcu **) | ||
328 | __get_free_pages(GFP_ATOMIC | __GFP_ZERO, | ||
329 | get_order(size)); | ||
330 | if (!buckets) { | ||
331 | kfree(ret); | ||
332 | return NULL; | ||
310 | } | 333 | } |
334 | ret->hash_buckets = buckets; | ||
335 | ret->hash_mask = entries - 1; | ||
336 | get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd)); | ||
311 | return ret; | 337 | return ret; |
312 | } | 338 | } |
313 | 339 | ||
314 | static void neigh_hash_free(struct neighbour **hash, unsigned int entries) | 340 | static void neigh_hash_free_rcu(struct rcu_head *head) |
315 | { | 341 | { |
316 | unsigned long size = entries * sizeof(struct neighbour *); | 342 | struct neigh_hash_table *nht = container_of(head, |
343 | struct neigh_hash_table, | ||
344 | rcu); | ||
345 | size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *); | ||
346 | struct neighbour __rcu **buckets = nht->hash_buckets; | ||
317 | 347 | ||
318 | if (size <= PAGE_SIZE) | 348 | if (size <= PAGE_SIZE) |
319 | kfree(hash); | 349 | kfree(buckets); |
320 | else | 350 | else |
321 | free_pages((unsigned long)hash, get_order(size)); | 351 | free_pages((unsigned long)buckets, get_order(size)); |
352 | kfree(nht); | ||
322 | } | 353 | } |
323 | 354 | ||
324 | static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries) | 355 | static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, |
356 | unsigned long new_entries) | ||
325 | { | 357 | { |
326 | struct neighbour **new_hash, **old_hash; | 358 | unsigned int i, hash; |
327 | unsigned int i, new_hash_mask, old_entries; | 359 | struct neigh_hash_table *new_nht, *old_nht; |
328 | 360 | ||
329 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); | 361 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); |
330 | 362 | ||
331 | BUG_ON(!is_power_of_2(new_entries)); | 363 | BUG_ON(!is_power_of_2(new_entries)); |
332 | new_hash = neigh_hash_alloc(new_entries); | 364 | old_nht = rcu_dereference_protected(tbl->nht, |
333 | if (!new_hash) | 365 | lockdep_is_held(&tbl->lock)); |
334 | return; | 366 | new_nht = neigh_hash_alloc(new_entries); |
335 | 367 | if (!new_nht) | |
336 | old_entries = tbl->hash_mask + 1; | 368 | return old_nht; |
337 | new_hash_mask = new_entries - 1; | ||
338 | old_hash = tbl->hash_buckets; | ||
339 | 369 | ||
340 | get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); | 370 | for (i = 0; i <= old_nht->hash_mask; i++) { |
341 | for (i = 0; i < old_entries; i++) { | ||
342 | struct neighbour *n, *next; | 371 | struct neighbour *n, *next; |
343 | 372 | ||
344 | for (n = old_hash[i]; n; n = next) { | 373 | for (n = rcu_dereference_protected(old_nht->hash_buckets[i], |
345 | unsigned int hash_val = tbl->hash(n->primary_key, n->dev); | 374 | lockdep_is_held(&tbl->lock)); |
346 | 375 | n != NULL; | |
347 | hash_val &= new_hash_mask; | 376 | n = next) { |
348 | next = n->next; | 377 | hash = tbl->hash(n->primary_key, n->dev, |
349 | 378 | new_nht->hash_rnd); | |
350 | n->next = new_hash[hash_val]; | 379 | |
351 | new_hash[hash_val] = n; | 380 | hash &= new_nht->hash_mask; |
381 | next = rcu_dereference_protected(n->next, | ||
382 | lockdep_is_held(&tbl->lock)); | ||
383 | |||
384 | rcu_assign_pointer(n->next, | ||
385 | rcu_dereference_protected( | ||
386 | new_nht->hash_buckets[hash], | ||
387 | lockdep_is_held(&tbl->lock))); | ||
388 | rcu_assign_pointer(new_nht->hash_buckets[hash], n); | ||
352 | } | 389 | } |
353 | } | 390 | } |
354 | tbl->hash_buckets = new_hash; | ||
355 | tbl->hash_mask = new_hash_mask; | ||
356 | 391 | ||
357 | neigh_hash_free(old_hash, old_entries); | 392 | rcu_assign_pointer(tbl->nht, new_nht); |
393 | call_rcu(&old_nht->rcu, neigh_hash_free_rcu); | ||
394 | return new_nht; | ||
358 | } | 395 | } |
359 | 396 | ||
360 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | 397 | struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, |
@@ -363,19 +400,26 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
363 | struct neighbour *n; | 400 | struct neighbour *n; |
364 | int key_len = tbl->key_len; | 401 | int key_len = tbl->key_len; |
365 | u32 hash_val; | 402 | u32 hash_val; |
403 | struct neigh_hash_table *nht; | ||
366 | 404 | ||
367 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 405 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
368 | 406 | ||
369 | read_lock_bh(&tbl->lock); | 407 | rcu_read_lock_bh(); |
370 | hash_val = tbl->hash(pkey, dev); | 408 | nht = rcu_dereference_bh(tbl->nht); |
371 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { | 409 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; |
410 | |||
411 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | ||
412 | n != NULL; | ||
413 | n = rcu_dereference_bh(n->next)) { | ||
372 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { | 414 | if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) { |
373 | neigh_hold(n); | 415 | if (!atomic_inc_not_zero(&n->refcnt)) |
416 | n = NULL; | ||
374 | NEIGH_CACHE_STAT_INC(tbl, hits); | 417 | NEIGH_CACHE_STAT_INC(tbl, hits); |
375 | break; | 418 | break; |
376 | } | 419 | } |
377 | } | 420 | } |
378 | read_unlock_bh(&tbl->lock); | 421 | |
422 | rcu_read_unlock_bh(); | ||
379 | return n; | 423 | return n; |
380 | } | 424 | } |
381 | EXPORT_SYMBOL(neigh_lookup); | 425 | EXPORT_SYMBOL(neigh_lookup); |
@@ -386,20 +430,27 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | |||
386 | struct neighbour *n; | 430 | struct neighbour *n; |
387 | int key_len = tbl->key_len; | 431 | int key_len = tbl->key_len; |
388 | u32 hash_val; | 432 | u32 hash_val; |
433 | struct neigh_hash_table *nht; | ||
389 | 434 | ||
390 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 435 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
391 | 436 | ||
392 | read_lock_bh(&tbl->lock); | 437 | rcu_read_lock_bh(); |
393 | hash_val = tbl->hash(pkey, NULL); | 438 | nht = rcu_dereference_bh(tbl->nht); |
394 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { | 439 | hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) & nht->hash_mask; |
440 | |||
441 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | ||
442 | n != NULL; | ||
443 | n = rcu_dereference_bh(n->next)) { | ||
395 | if (!memcmp(n->primary_key, pkey, key_len) && | 444 | if (!memcmp(n->primary_key, pkey, key_len) && |
396 | net_eq(dev_net(n->dev), net)) { | 445 | net_eq(dev_net(n->dev), net)) { |
397 | neigh_hold(n); | 446 | if (!atomic_inc_not_zero(&n->refcnt)) |
447 | n = NULL; | ||
398 | NEIGH_CACHE_STAT_INC(tbl, hits); | 448 | NEIGH_CACHE_STAT_INC(tbl, hits); |
399 | break; | 449 | break; |
400 | } | 450 | } |
401 | } | 451 | } |
402 | read_unlock_bh(&tbl->lock); | 452 | |
453 | rcu_read_unlock_bh(); | ||
403 | return n; | 454 | return n; |
404 | } | 455 | } |
405 | EXPORT_SYMBOL(neigh_lookup_nodev); | 456 | EXPORT_SYMBOL(neigh_lookup_nodev); |
@@ -411,6 +462,7 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | |||
411 | int key_len = tbl->key_len; | 462 | int key_len = tbl->key_len; |
412 | int error; | 463 | int error; |
413 | struct neighbour *n1, *rc, *n = neigh_alloc(tbl); | 464 | struct neighbour *n1, *rc, *n = neigh_alloc(tbl); |
465 | struct neigh_hash_table *nht; | ||
414 | 466 | ||
415 | if (!n) { | 467 | if (!n) { |
416 | rc = ERR_PTR(-ENOBUFS); | 468 | rc = ERR_PTR(-ENOBUFS); |
@@ -437,18 +489,24 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | |||
437 | n->confirmed = jiffies - (n->parms->base_reachable_time << 1); | 489 | n->confirmed = jiffies - (n->parms->base_reachable_time << 1); |
438 | 490 | ||
439 | write_lock_bh(&tbl->lock); | 491 | write_lock_bh(&tbl->lock); |
492 | nht = rcu_dereference_protected(tbl->nht, | ||
493 | lockdep_is_held(&tbl->lock)); | ||
440 | 494 | ||
441 | if (atomic_read(&tbl->entries) > (tbl->hash_mask + 1)) | 495 | if (atomic_read(&tbl->entries) > (nht->hash_mask + 1)) |
442 | neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1); | 496 | nht = neigh_hash_grow(tbl, (nht->hash_mask + 1) << 1); |
443 | 497 | ||
444 | hash_val = tbl->hash(pkey, dev) & tbl->hash_mask; | 498 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; |
445 | 499 | ||
446 | if (n->parms->dead) { | 500 | if (n->parms->dead) { |
447 | rc = ERR_PTR(-EINVAL); | 501 | rc = ERR_PTR(-EINVAL); |
448 | goto out_tbl_unlock; | 502 | goto out_tbl_unlock; |
449 | } | 503 | } |
450 | 504 | ||
451 | for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) { | 505 | for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val], |
506 | lockdep_is_held(&tbl->lock)); | ||
507 | n1 != NULL; | ||
508 | n1 = rcu_dereference_protected(n1->next, | ||
509 | lockdep_is_held(&tbl->lock))) { | ||
452 | if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) { | 510 | if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) { |
453 | neigh_hold(n1); | 511 | neigh_hold(n1); |
454 | rc = n1; | 512 | rc = n1; |
@@ -456,10 +514,12 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | |||
456 | } | 514 | } |
457 | } | 515 | } |
458 | 516 | ||
459 | n->next = tbl->hash_buckets[hash_val]; | ||
460 | tbl->hash_buckets[hash_val] = n; | ||
461 | n->dead = 0; | 517 | n->dead = 0; |
462 | neigh_hold(n); | 518 | neigh_hold(n); |
519 | rcu_assign_pointer(n->next, | ||
520 | rcu_dereference_protected(nht->hash_buckets[hash_val], | ||
521 | lockdep_is_held(&tbl->lock))); | ||
522 | rcu_assign_pointer(nht->hash_buckets[hash_val], n); | ||
463 | write_unlock_bh(&tbl->lock); | 523 | write_unlock_bh(&tbl->lock); |
464 | NEIGH_PRINTK2("neigh %p is created.\n", n); | 524 | NEIGH_PRINTK2("neigh %p is created.\n", n); |
465 | rc = n; | 525 | rc = n; |
@@ -616,6 +676,12 @@ static inline void neigh_parms_put(struct neigh_parms *parms) | |||
616 | neigh_parms_destroy(parms); | 676 | neigh_parms_destroy(parms); |
617 | } | 677 | } |
618 | 678 | ||
679 | static void neigh_destroy_rcu(struct rcu_head *head) | ||
680 | { | ||
681 | struct neighbour *neigh = container_of(head, struct neighbour, rcu); | ||
682 | |||
683 | kmem_cache_free(neigh->tbl->kmem_cachep, neigh); | ||
684 | } | ||
619 | /* | 685 | /* |
620 | * neighbour must already be out of the table; | 686 | * neighbour must already be out of the table; |
621 | * | 687 | * |
@@ -643,8 +709,7 @@ void neigh_destroy(struct neighbour *neigh) | |||
643 | write_seqlock_bh(&hh->hh_lock); | 709 | write_seqlock_bh(&hh->hh_lock); |
644 | hh->hh_output = neigh_blackhole; | 710 | hh->hh_output = neigh_blackhole; |
645 | write_sequnlock_bh(&hh->hh_lock); | 711 | write_sequnlock_bh(&hh->hh_lock); |
646 | if (atomic_dec_and_test(&hh->hh_refcnt)) | 712 | hh_cache_put(hh); |
647 | kfree(hh); | ||
648 | } | 713 | } |
649 | 714 | ||
650 | skb_queue_purge(&neigh->arp_queue); | 715 | skb_queue_purge(&neigh->arp_queue); |
@@ -655,7 +720,7 @@ void neigh_destroy(struct neighbour *neigh) | |||
655 | NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh); | 720 | NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh); |
656 | 721 | ||
657 | atomic_dec(&neigh->tbl->entries); | 722 | atomic_dec(&neigh->tbl->entries); |
658 | kmem_cache_free(neigh->tbl->kmem_cachep, neigh); | 723 | call_rcu(&neigh->rcu, neigh_destroy_rcu); |
659 | } | 724 | } |
660 | EXPORT_SYMBOL(neigh_destroy); | 725 | EXPORT_SYMBOL(neigh_destroy); |
661 | 726 | ||
@@ -696,12 +761,16 @@ static void neigh_connect(struct neighbour *neigh) | |||
696 | static void neigh_periodic_work(struct work_struct *work) | 761 | static void neigh_periodic_work(struct work_struct *work) |
697 | { | 762 | { |
698 | struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work); | 763 | struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work); |
699 | struct neighbour *n, **np; | 764 | struct neighbour *n; |
765 | struct neighbour __rcu **np; | ||
700 | unsigned int i; | 766 | unsigned int i; |
767 | struct neigh_hash_table *nht; | ||
701 | 768 | ||
702 | NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs); | 769 | NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs); |
703 | 770 | ||
704 | write_lock_bh(&tbl->lock); | 771 | write_lock_bh(&tbl->lock); |
772 | nht = rcu_dereference_protected(tbl->nht, | ||
773 | lockdep_is_held(&tbl->lock)); | ||
705 | 774 | ||
706 | /* | 775 | /* |
707 | * periodically recompute ReachableTime from random function | 776 | * periodically recompute ReachableTime from random function |
@@ -715,10 +784,11 @@ static void neigh_periodic_work(struct work_struct *work) | |||
715 | neigh_rand_reach_time(p->base_reachable_time); | 784 | neigh_rand_reach_time(p->base_reachable_time); |
716 | } | 785 | } |
717 | 786 | ||
718 | for (i = 0 ; i <= tbl->hash_mask; i++) { | 787 | for (i = 0 ; i <= nht->hash_mask; i++) { |
719 | np = &tbl->hash_buckets[i]; | 788 | np = &nht->hash_buckets[i]; |
720 | 789 | ||
721 | while ((n = *np) != NULL) { | 790 | while ((n = rcu_dereference_protected(*np, |
791 | lockdep_is_held(&tbl->lock))) != NULL) { | ||
722 | unsigned int state; | 792 | unsigned int state; |
723 | 793 | ||
724 | write_lock(&n->lock); | 794 | write_lock(&n->lock); |
@@ -766,9 +836,9 @@ next_elt: | |||
766 | static __inline__ int neigh_max_probes(struct neighbour *n) | 836 | static __inline__ int neigh_max_probes(struct neighbour *n) |
767 | { | 837 | { |
768 | struct neigh_parms *p = n->parms; | 838 | struct neigh_parms *p = n->parms; |
769 | return (n->nud_state & NUD_PROBE ? | 839 | return (n->nud_state & NUD_PROBE) ? |
770 | p->ucast_probes : | 840 | p->ucast_probes : |
771 | p->ucast_probes + p->app_probes + p->mcast_probes); | 841 | p->ucast_probes + p->app_probes + p->mcast_probes; |
772 | } | 842 | } |
773 | 843 | ||
774 | static void neigh_invalidate(struct neighbour *neigh) | 844 | static void neigh_invalidate(struct neighbour *neigh) |
@@ -945,7 +1015,7 @@ out_unlock_bh: | |||
945 | } | 1015 | } |
946 | EXPORT_SYMBOL(__neigh_event_send); | 1016 | EXPORT_SYMBOL(__neigh_event_send); |
947 | 1017 | ||
948 | static void neigh_update_hhs(struct neighbour *neigh) | 1018 | static void neigh_update_hhs(const struct neighbour *neigh) |
949 | { | 1019 | { |
950 | struct hh_cache *hh; | 1020 | struct hh_cache *hh; |
951 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) | 1021 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) |
@@ -1081,7 +1151,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
1081 | } | 1151 | } |
1082 | 1152 | ||
1083 | if (lladdr != neigh->ha) { | 1153 | if (lladdr != neigh->ha) { |
1154 | write_seqlock(&neigh->ha_lock); | ||
1084 | memcpy(&neigh->ha, lladdr, dev->addr_len); | 1155 | memcpy(&neigh->ha, lladdr, dev->addr_len); |
1156 | write_sequnlock(&neigh->ha_lock); | ||
1085 | neigh_update_hhs(neigh); | 1157 | neigh_update_hhs(neigh); |
1086 | if (!(new & NUD_CONNECTED)) | 1158 | if (!(new & NUD_CONNECTED)) |
1087 | neigh->confirmed = jiffies - | 1159 | neigh->confirmed = jiffies - |
@@ -1139,44 +1211,73 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
1139 | } | 1211 | } |
1140 | EXPORT_SYMBOL(neigh_event_ns); | 1212 | EXPORT_SYMBOL(neigh_event_ns); |
1141 | 1213 | ||
1214 | static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst, | ||
1215 | __be16 protocol) | ||
1216 | { | ||
1217 | struct hh_cache *hh; | ||
1218 | |||
1219 | smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */ | ||
1220 | for (hh = n->hh; hh; hh = hh->hh_next) { | ||
1221 | if (hh->hh_type == protocol) { | ||
1222 | atomic_inc(&hh->hh_refcnt); | ||
1223 | if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) | ||
1224 | hh_cache_put(hh); | ||
1225 | return true; | ||
1226 | } | ||
1227 | } | ||
1228 | return false; | ||
1229 | } | ||
1230 | |||
1231 | /* called with read_lock_bh(&n->lock); */ | ||
1142 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | 1232 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, |
1143 | __be16 protocol) | 1233 | __be16 protocol) |
1144 | { | 1234 | { |
1145 | struct hh_cache *hh; | 1235 | struct hh_cache *hh; |
1146 | struct net_device *dev = dst->dev; | 1236 | struct net_device *dev = dst->dev; |
1147 | 1237 | ||
1148 | for (hh = n->hh; hh; hh = hh->hh_next) | 1238 | if (likely(neigh_hh_lookup(n, dst, protocol))) |
1149 | if (hh->hh_type == protocol) | 1239 | return; |
1150 | break; | ||
1151 | 1240 | ||
1152 | if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) { | 1241 | /* slow path */ |
1153 | seqlock_init(&hh->hh_lock); | 1242 | hh = kzalloc(sizeof(*hh), GFP_ATOMIC); |
1154 | hh->hh_type = protocol; | 1243 | if (!hh) |
1155 | atomic_set(&hh->hh_refcnt, 0); | 1244 | return; |
1156 | hh->hh_next = NULL; | ||
1157 | 1245 | ||
1158 | if (dev->header_ops->cache(n, hh)) { | 1246 | seqlock_init(&hh->hh_lock); |
1159 | kfree(hh); | 1247 | hh->hh_type = protocol; |
1160 | hh = NULL; | 1248 | atomic_set(&hh->hh_refcnt, 2); |
1161 | } else { | 1249 | |
1162 | atomic_inc(&hh->hh_refcnt); | 1250 | if (dev->header_ops->cache(n, hh)) { |
1163 | hh->hh_next = n->hh; | 1251 | kfree(hh); |
1164 | n->hh = hh; | 1252 | return; |
1165 | if (n->nud_state & NUD_CONNECTED) | ||
1166 | hh->hh_output = n->ops->hh_output; | ||
1167 | else | ||
1168 | hh->hh_output = n->ops->output; | ||
1169 | } | ||
1170 | } | 1253 | } |
1171 | if (hh) { | 1254 | |
1172 | atomic_inc(&hh->hh_refcnt); | 1255 | write_lock_bh(&n->lock); |
1173 | dst->hh = hh; | 1256 | |
1257 | /* must check if another thread already did the insert */ | ||
1258 | if (neigh_hh_lookup(n, dst, protocol)) { | ||
1259 | kfree(hh); | ||
1260 | goto end; | ||
1174 | } | 1261 | } |
1262 | |||
1263 | if (n->nud_state & NUD_CONNECTED) | ||
1264 | hh->hh_output = n->ops->hh_output; | ||
1265 | else | ||
1266 | hh->hh_output = n->ops->output; | ||
1267 | |||
1268 | hh->hh_next = n->hh; | ||
1269 | smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */ | ||
1270 | n->hh = hh; | ||
1271 | |||
1272 | if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) | ||
1273 | hh_cache_put(hh); | ||
1274 | end: | ||
1275 | write_unlock_bh(&n->lock); | ||
1175 | } | 1276 | } |
1176 | 1277 | ||
1177 | /* This function can be used in contexts, where only old dev_queue_xmit | 1278 | /* This function can be used in contexts, where only old dev_queue_xmit |
1178 | worked, f.e. if you want to override normal output path (eql, shaper), | 1279 | * worked, f.e. if you want to override normal output path (eql, shaper), |
1179 | but resolution is not made yet. | 1280 | * but resolution is not made yet. |
1180 | */ | 1281 | */ |
1181 | 1282 | ||
1182 | int neigh_compat_output(struct sk_buff *skb) | 1283 | int neigh_compat_output(struct sk_buff *skb) |
@@ -1210,19 +1311,19 @@ int neigh_resolve_output(struct sk_buff *skb) | |||
1210 | if (!neigh_event_send(neigh, skb)) { | 1311 | if (!neigh_event_send(neigh, skb)) { |
1211 | int err; | 1312 | int err; |
1212 | struct net_device *dev = neigh->dev; | 1313 | struct net_device *dev = neigh->dev; |
1213 | if (dev->header_ops->cache && !dst->hh) { | 1314 | unsigned int seq; |
1214 | write_lock_bh(&neigh->lock); | 1315 | |
1215 | if (!dst->hh) | 1316 | if (dev->header_ops->cache && |
1216 | neigh_hh_init(neigh, dst, dst->ops->protocol); | 1317 | !dst->hh && |
1217 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1318 | !(dst->flags & DST_NOCACHE)) |
1218 | neigh->ha, NULL, skb->len); | 1319 | neigh_hh_init(neigh, dst, dst->ops->protocol); |
1219 | write_unlock_bh(&neigh->lock); | 1320 | |
1220 | } else { | 1321 | do { |
1221 | read_lock_bh(&neigh->lock); | 1322 | seq = read_seqbegin(&neigh->ha_lock); |
1222 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1323 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
1223 | neigh->ha, NULL, skb->len); | 1324 | neigh->ha, NULL, skb->len); |
1224 | read_unlock_bh(&neigh->lock); | 1325 | } while (read_seqretry(&neigh->ha_lock, seq)); |
1225 | } | 1326 | |
1226 | if (err >= 0) | 1327 | if (err >= 0) |
1227 | rc = neigh->ops->queue_xmit(skb); | 1328 | rc = neigh->ops->queue_xmit(skb); |
1228 | else | 1329 | else |
@@ -1248,13 +1349,16 @@ int neigh_connected_output(struct sk_buff *skb) | |||
1248 | struct dst_entry *dst = skb_dst(skb); | 1349 | struct dst_entry *dst = skb_dst(skb); |
1249 | struct neighbour *neigh = dst->neighbour; | 1350 | struct neighbour *neigh = dst->neighbour; |
1250 | struct net_device *dev = neigh->dev; | 1351 | struct net_device *dev = neigh->dev; |
1352 | unsigned int seq; | ||
1251 | 1353 | ||
1252 | __skb_pull(skb, skb_network_offset(skb)); | 1354 | __skb_pull(skb, skb_network_offset(skb)); |
1253 | 1355 | ||
1254 | read_lock_bh(&neigh->lock); | 1356 | do { |
1255 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | 1357 | seq = read_seqbegin(&neigh->ha_lock); |
1256 | neigh->ha, NULL, skb->len); | 1358 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), |
1257 | read_unlock_bh(&neigh->lock); | 1359 | neigh->ha, NULL, skb->len); |
1360 | } while (read_seqretry(&neigh->ha_lock, seq)); | ||
1361 | |||
1258 | if (err >= 0) | 1362 | if (err >= 0) |
1259 | err = neigh->ops->queue_xmit(skb); | 1363 | err = neigh->ops->queue_xmit(skb); |
1260 | else { | 1364 | else { |
@@ -1436,17 +1540,14 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1436 | panic("cannot create neighbour proc dir entry"); | 1540 | panic("cannot create neighbour proc dir entry"); |
1437 | #endif | 1541 | #endif |
1438 | 1542 | ||
1439 | tbl->hash_mask = 1; | 1543 | RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8)); |
1440 | tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1); | ||
1441 | 1544 | ||
1442 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); | 1545 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); |
1443 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); | 1546 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); |
1444 | 1547 | ||
1445 | if (!tbl->hash_buckets || !tbl->phash_buckets) | 1548 | if (!tbl->nht || !tbl->phash_buckets) |
1446 | panic("cannot allocate neighbour cache hashes"); | 1549 | panic("cannot allocate neighbour cache hashes"); |
1447 | 1550 | ||
1448 | get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd)); | ||
1449 | |||
1450 | rwlock_init(&tbl->lock); | 1551 | rwlock_init(&tbl->lock); |
1451 | INIT_DELAYED_WORK_DEFERRABLE(&tbl->gc_work, neigh_periodic_work); | 1552 | INIT_DELAYED_WORK_DEFERRABLE(&tbl->gc_work, neigh_periodic_work); |
1452 | schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time); | 1553 | schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time); |
@@ -1486,8 +1587,7 @@ int neigh_table_clear(struct neigh_table *tbl) | |||
1486 | struct neigh_table **tp; | 1587 | struct neigh_table **tp; |
1487 | 1588 | ||
1488 | /* It is not clean... Fix it to unload IPv6 module safely */ | 1589 | /* It is not clean... Fix it to unload IPv6 module safely */ |
1489 | cancel_delayed_work(&tbl->gc_work); | 1590 | cancel_delayed_work_sync(&tbl->gc_work); |
1490 | flush_scheduled_work(); | ||
1491 | del_timer_sync(&tbl->proxy_timer); | 1591 | del_timer_sync(&tbl->proxy_timer); |
1492 | pneigh_queue_purge(&tbl->proxy_queue); | 1592 | pneigh_queue_purge(&tbl->proxy_queue); |
1493 | neigh_ifdown(tbl, NULL); | 1593 | neigh_ifdown(tbl, NULL); |
@@ -1502,8 +1602,9 @@ int neigh_table_clear(struct neigh_table *tbl) | |||
1502 | } | 1602 | } |
1503 | write_unlock(&neigh_tbl_lock); | 1603 | write_unlock(&neigh_tbl_lock); |
1504 | 1604 | ||
1505 | neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1); | 1605 | call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu, |
1506 | tbl->hash_buckets = NULL; | 1606 | neigh_hash_free_rcu); |
1607 | tbl->nht = NULL; | ||
1507 | 1608 | ||
1508 | kfree(tbl->phash_buckets); | 1609 | kfree(tbl->phash_buckets); |
1509 | tbl->phash_buckets = NULL; | 1610 | tbl->phash_buckets = NULL; |
@@ -1529,6 +1630,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1529 | struct net_device *dev = NULL; | 1630 | struct net_device *dev = NULL; |
1530 | int err = -EINVAL; | 1631 | int err = -EINVAL; |
1531 | 1632 | ||
1633 | ASSERT_RTNL(); | ||
1532 | if (nlmsg_len(nlh) < sizeof(*ndm)) | 1634 | if (nlmsg_len(nlh) < sizeof(*ndm)) |
1533 | goto out; | 1635 | goto out; |
1534 | 1636 | ||
@@ -1538,7 +1640,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1538 | 1640 | ||
1539 | ndm = nlmsg_data(nlh); | 1641 | ndm = nlmsg_data(nlh); |
1540 | if (ndm->ndm_ifindex) { | 1642 | if (ndm->ndm_ifindex) { |
1541 | dev = dev_get_by_index(net, ndm->ndm_ifindex); | 1643 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); |
1542 | if (dev == NULL) { | 1644 | if (dev == NULL) { |
1543 | err = -ENODEV; | 1645 | err = -ENODEV; |
1544 | goto out; | 1646 | goto out; |
@@ -1554,34 +1656,31 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1554 | read_unlock(&neigh_tbl_lock); | 1656 | read_unlock(&neigh_tbl_lock); |
1555 | 1657 | ||
1556 | if (nla_len(dst_attr) < tbl->key_len) | 1658 | if (nla_len(dst_attr) < tbl->key_len) |
1557 | goto out_dev_put; | 1659 | goto out; |
1558 | 1660 | ||
1559 | if (ndm->ndm_flags & NTF_PROXY) { | 1661 | if (ndm->ndm_flags & NTF_PROXY) { |
1560 | err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); | 1662 | err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); |
1561 | goto out_dev_put; | 1663 | goto out; |
1562 | } | 1664 | } |
1563 | 1665 | ||
1564 | if (dev == NULL) | 1666 | if (dev == NULL) |
1565 | goto out_dev_put; | 1667 | goto out; |
1566 | 1668 | ||
1567 | neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); | 1669 | neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); |
1568 | if (neigh == NULL) { | 1670 | if (neigh == NULL) { |
1569 | err = -ENOENT; | 1671 | err = -ENOENT; |
1570 | goto out_dev_put; | 1672 | goto out; |
1571 | } | 1673 | } |
1572 | 1674 | ||
1573 | err = neigh_update(neigh, NULL, NUD_FAILED, | 1675 | err = neigh_update(neigh, NULL, NUD_FAILED, |
1574 | NEIGH_UPDATE_F_OVERRIDE | | 1676 | NEIGH_UPDATE_F_OVERRIDE | |
1575 | NEIGH_UPDATE_F_ADMIN); | 1677 | NEIGH_UPDATE_F_ADMIN); |
1576 | neigh_release(neigh); | 1678 | neigh_release(neigh); |
1577 | goto out_dev_put; | 1679 | goto out; |
1578 | } | 1680 | } |
1579 | read_unlock(&neigh_tbl_lock); | 1681 | read_unlock(&neigh_tbl_lock); |
1580 | err = -EAFNOSUPPORT; | 1682 | err = -EAFNOSUPPORT; |
1581 | 1683 | ||
1582 | out_dev_put: | ||
1583 | if (dev) | ||
1584 | dev_put(dev); | ||
1585 | out: | 1684 | out: |
1586 | return err; | 1685 | return err; |
1587 | } | 1686 | } |
@@ -1595,6 +1694,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1595 | struct net_device *dev = NULL; | 1694 | struct net_device *dev = NULL; |
1596 | int err; | 1695 | int err; |
1597 | 1696 | ||
1697 | ASSERT_RTNL(); | ||
1598 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); | 1698 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); |
1599 | if (err < 0) | 1699 | if (err < 0) |
1600 | goto out; | 1700 | goto out; |
@@ -1605,14 +1705,14 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1605 | 1705 | ||
1606 | ndm = nlmsg_data(nlh); | 1706 | ndm = nlmsg_data(nlh); |
1607 | if (ndm->ndm_ifindex) { | 1707 | if (ndm->ndm_ifindex) { |
1608 | dev = dev_get_by_index(net, ndm->ndm_ifindex); | 1708 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); |
1609 | if (dev == NULL) { | 1709 | if (dev == NULL) { |
1610 | err = -ENODEV; | 1710 | err = -ENODEV; |
1611 | goto out; | 1711 | goto out; |
1612 | } | 1712 | } |
1613 | 1713 | ||
1614 | if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) | 1714 | if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) |
1615 | goto out_dev_put; | 1715 | goto out; |
1616 | } | 1716 | } |
1617 | 1717 | ||
1618 | read_lock(&neigh_tbl_lock); | 1718 | read_lock(&neigh_tbl_lock); |
@@ -1626,7 +1726,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1626 | read_unlock(&neigh_tbl_lock); | 1726 | read_unlock(&neigh_tbl_lock); |
1627 | 1727 | ||
1628 | if (nla_len(tb[NDA_DST]) < tbl->key_len) | 1728 | if (nla_len(tb[NDA_DST]) < tbl->key_len) |
1629 | goto out_dev_put; | 1729 | goto out; |
1630 | dst = nla_data(tb[NDA_DST]); | 1730 | dst = nla_data(tb[NDA_DST]); |
1631 | lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; | 1731 | lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; |
1632 | 1732 | ||
@@ -1639,29 +1739,29 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1639 | pn->flags = ndm->ndm_flags; | 1739 | pn->flags = ndm->ndm_flags; |
1640 | err = 0; | 1740 | err = 0; |
1641 | } | 1741 | } |
1642 | goto out_dev_put; | 1742 | goto out; |
1643 | } | 1743 | } |
1644 | 1744 | ||
1645 | if (dev == NULL) | 1745 | if (dev == NULL) |
1646 | goto out_dev_put; | 1746 | goto out; |
1647 | 1747 | ||
1648 | neigh = neigh_lookup(tbl, dst, dev); | 1748 | neigh = neigh_lookup(tbl, dst, dev); |
1649 | if (neigh == NULL) { | 1749 | if (neigh == NULL) { |
1650 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | 1750 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { |
1651 | err = -ENOENT; | 1751 | err = -ENOENT; |
1652 | goto out_dev_put; | 1752 | goto out; |
1653 | } | 1753 | } |
1654 | 1754 | ||
1655 | neigh = __neigh_lookup_errno(tbl, dst, dev); | 1755 | neigh = __neigh_lookup_errno(tbl, dst, dev); |
1656 | if (IS_ERR(neigh)) { | 1756 | if (IS_ERR(neigh)) { |
1657 | err = PTR_ERR(neigh); | 1757 | err = PTR_ERR(neigh); |
1658 | goto out_dev_put; | 1758 | goto out; |
1659 | } | 1759 | } |
1660 | } else { | 1760 | } else { |
1661 | if (nlh->nlmsg_flags & NLM_F_EXCL) { | 1761 | if (nlh->nlmsg_flags & NLM_F_EXCL) { |
1662 | err = -EEXIST; | 1762 | err = -EEXIST; |
1663 | neigh_release(neigh); | 1763 | neigh_release(neigh); |
1664 | goto out_dev_put; | 1764 | goto out; |
1665 | } | 1765 | } |
1666 | 1766 | ||
1667 | if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) | 1767 | if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) |
@@ -1674,15 +1774,11 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1674 | } else | 1774 | } else |
1675 | err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); | 1775 | err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); |
1676 | neigh_release(neigh); | 1776 | neigh_release(neigh); |
1677 | goto out_dev_put; | 1777 | goto out; |
1678 | } | 1778 | } |
1679 | 1779 | ||
1680 | read_unlock(&neigh_tbl_lock); | 1780 | read_unlock(&neigh_tbl_lock); |
1681 | err = -EAFNOSUPPORT; | 1781 | err = -EAFNOSUPPORT; |
1682 | |||
1683 | out_dev_put: | ||
1684 | if (dev) | ||
1685 | dev_put(dev); | ||
1686 | out: | 1782 | out: |
1687 | return err; | 1783 | return err; |
1688 | } | 1784 | } |
@@ -1748,18 +1844,22 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |||
1748 | unsigned long now = jiffies; | 1844 | unsigned long now = jiffies; |
1749 | unsigned int flush_delta = now - tbl->last_flush; | 1845 | unsigned int flush_delta = now - tbl->last_flush; |
1750 | unsigned int rand_delta = now - tbl->last_rand; | 1846 | unsigned int rand_delta = now - tbl->last_rand; |
1751 | 1847 | struct neigh_hash_table *nht; | |
1752 | struct ndt_config ndc = { | 1848 | struct ndt_config ndc = { |
1753 | .ndtc_key_len = tbl->key_len, | 1849 | .ndtc_key_len = tbl->key_len, |
1754 | .ndtc_entry_size = tbl->entry_size, | 1850 | .ndtc_entry_size = tbl->entry_size, |
1755 | .ndtc_entries = atomic_read(&tbl->entries), | 1851 | .ndtc_entries = atomic_read(&tbl->entries), |
1756 | .ndtc_last_flush = jiffies_to_msecs(flush_delta), | 1852 | .ndtc_last_flush = jiffies_to_msecs(flush_delta), |
1757 | .ndtc_last_rand = jiffies_to_msecs(rand_delta), | 1853 | .ndtc_last_rand = jiffies_to_msecs(rand_delta), |
1758 | .ndtc_hash_rnd = tbl->hash_rnd, | ||
1759 | .ndtc_hash_mask = tbl->hash_mask, | ||
1760 | .ndtc_proxy_qlen = tbl->proxy_queue.qlen, | 1854 | .ndtc_proxy_qlen = tbl->proxy_queue.qlen, |
1761 | }; | 1855 | }; |
1762 | 1856 | ||
1857 | rcu_read_lock_bh(); | ||
1858 | nht = rcu_dereference_bh(tbl->nht); | ||
1859 | ndc.ndtc_hash_rnd = nht->hash_rnd; | ||
1860 | ndc.ndtc_hash_mask = nht->hash_mask; | ||
1861 | rcu_read_unlock_bh(); | ||
1862 | |||
1763 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | 1863 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); |
1764 | } | 1864 | } |
1765 | 1865 | ||
@@ -2056,10 +2156,14 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, | |||
2056 | 2156 | ||
2057 | read_lock_bh(&neigh->lock); | 2157 | read_lock_bh(&neigh->lock); |
2058 | ndm->ndm_state = neigh->nud_state; | 2158 | ndm->ndm_state = neigh->nud_state; |
2059 | if ((neigh->nud_state & NUD_VALID) && | 2159 | if (neigh->nud_state & NUD_VALID) { |
2060 | nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) { | 2160 | char haddr[MAX_ADDR_LEN]; |
2061 | read_unlock_bh(&neigh->lock); | 2161 | |
2062 | goto nla_put_failure; | 2162 | neigh_ha_snapshot(haddr, neigh, neigh->dev); |
2163 | if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) { | ||
2164 | read_unlock_bh(&neigh->lock); | ||
2165 | goto nla_put_failure; | ||
2166 | } | ||
2063 | } | 2167 | } |
2064 | 2168 | ||
2065 | ci.ndm_used = jiffies_to_clock_t(now - neigh->used); | 2169 | ci.ndm_used = jiffies_to_clock_t(now - neigh->used); |
@@ -2087,18 +2191,23 @@ static void neigh_update_notify(struct neighbour *neigh) | |||
2087 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | 2191 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, |
2088 | struct netlink_callback *cb) | 2192 | struct netlink_callback *cb) |
2089 | { | 2193 | { |
2090 | struct net * net = sock_net(skb->sk); | 2194 | struct net *net = sock_net(skb->sk); |
2091 | struct neighbour *n; | 2195 | struct neighbour *n; |
2092 | int rc, h, s_h = cb->args[1]; | 2196 | int rc, h, s_h = cb->args[1]; |
2093 | int idx, s_idx = idx = cb->args[2]; | 2197 | int idx, s_idx = idx = cb->args[2]; |
2198 | struct neigh_hash_table *nht; | ||
2094 | 2199 | ||
2095 | read_lock_bh(&tbl->lock); | 2200 | rcu_read_lock_bh(); |
2096 | for (h = 0; h <= tbl->hash_mask; h++) { | 2201 | nht = rcu_dereference_bh(tbl->nht); |
2202 | |||
2203 | for (h = 0; h <= nht->hash_mask; h++) { | ||
2097 | if (h < s_h) | 2204 | if (h < s_h) |
2098 | continue; | 2205 | continue; |
2099 | if (h > s_h) | 2206 | if (h > s_h) |
2100 | s_idx = 0; | 2207 | s_idx = 0; |
2101 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { | 2208 | for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; |
2209 | n != NULL; | ||
2210 | n = rcu_dereference_bh(n->next)) { | ||
2102 | if (!net_eq(dev_net(n->dev), net)) | 2211 | if (!net_eq(dev_net(n->dev), net)) |
2103 | continue; | 2212 | continue; |
2104 | if (idx < s_idx) | 2213 | if (idx < s_idx) |
@@ -2107,17 +2216,16 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
2107 | cb->nlh->nlmsg_seq, | 2216 | cb->nlh->nlmsg_seq, |
2108 | RTM_NEWNEIGH, | 2217 | RTM_NEWNEIGH, |
2109 | NLM_F_MULTI) <= 0) { | 2218 | NLM_F_MULTI) <= 0) { |
2110 | read_unlock_bh(&tbl->lock); | ||
2111 | rc = -1; | 2219 | rc = -1; |
2112 | goto out; | 2220 | goto out; |
2113 | } | 2221 | } |
2114 | next: | 2222 | next: |
2115 | idx++; | 2223 | idx++; |
2116 | } | 2224 | } |
2117 | } | 2225 | } |
2118 | read_unlock_bh(&tbl->lock); | ||
2119 | rc = skb->len; | 2226 | rc = skb->len; |
2120 | out: | 2227 | out: |
2228 | rcu_read_unlock_bh(); | ||
2121 | cb->args[1] = h; | 2229 | cb->args[1] = h; |
2122 | cb->args[2] = idx; | 2230 | cb->args[2] = idx; |
2123 | return rc; | 2231 | return rc; |
@@ -2150,15 +2258,22 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
2150 | void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie) | 2258 | void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie) |
2151 | { | 2259 | { |
2152 | int chain; | 2260 | int chain; |
2261 | struct neigh_hash_table *nht; | ||
2153 | 2262 | ||
2154 | read_lock_bh(&tbl->lock); | 2263 | rcu_read_lock_bh(); |
2155 | for (chain = 0; chain <= tbl->hash_mask; chain++) { | 2264 | nht = rcu_dereference_bh(tbl->nht); |
2265 | |||
2266 | read_lock(&tbl->lock); /* avoid resizes */ | ||
2267 | for (chain = 0; chain <= nht->hash_mask; chain++) { | ||
2156 | struct neighbour *n; | 2268 | struct neighbour *n; |
2157 | 2269 | ||
2158 | for (n = tbl->hash_buckets[chain]; n; n = n->next) | 2270 | for (n = rcu_dereference_bh(nht->hash_buckets[chain]); |
2271 | n != NULL; | ||
2272 | n = rcu_dereference_bh(n->next)) | ||
2159 | cb(n, cookie); | 2273 | cb(n, cookie); |
2160 | } | 2274 | } |
2161 | read_unlock_bh(&tbl->lock); | 2275 | read_unlock(&tbl->lock); |
2276 | rcu_read_unlock_bh(); | ||
2162 | } | 2277 | } |
2163 | EXPORT_SYMBOL(neigh_for_each); | 2278 | EXPORT_SYMBOL(neigh_for_each); |
2164 | 2279 | ||
@@ -2167,18 +2282,25 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
2167 | int (*cb)(struct neighbour *)) | 2282 | int (*cb)(struct neighbour *)) |
2168 | { | 2283 | { |
2169 | int chain; | 2284 | int chain; |
2285 | struct neigh_hash_table *nht; | ||
2170 | 2286 | ||
2171 | for (chain = 0; chain <= tbl->hash_mask; chain++) { | 2287 | nht = rcu_dereference_protected(tbl->nht, |
2172 | struct neighbour *n, **np; | 2288 | lockdep_is_held(&tbl->lock)); |
2289 | for (chain = 0; chain <= nht->hash_mask; chain++) { | ||
2290 | struct neighbour *n; | ||
2291 | struct neighbour __rcu **np; | ||
2173 | 2292 | ||
2174 | np = &tbl->hash_buckets[chain]; | 2293 | np = &nht->hash_buckets[chain]; |
2175 | while ((n = *np) != NULL) { | 2294 | while ((n = rcu_dereference_protected(*np, |
2295 | lockdep_is_held(&tbl->lock))) != NULL) { | ||
2176 | int release; | 2296 | int release; |
2177 | 2297 | ||
2178 | write_lock(&n->lock); | 2298 | write_lock(&n->lock); |
2179 | release = cb(n); | 2299 | release = cb(n); |
2180 | if (release) { | 2300 | if (release) { |
2181 | *np = n->next; | 2301 | rcu_assign_pointer(*np, |
2302 | rcu_dereference_protected(n->next, | ||
2303 | lockdep_is_held(&tbl->lock))); | ||
2182 | n->dead = 1; | 2304 | n->dead = 1; |
2183 | } else | 2305 | } else |
2184 | np = &n->next; | 2306 | np = &n->next; |
@@ -2196,13 +2318,13 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
2196 | { | 2318 | { |
2197 | struct neigh_seq_state *state = seq->private; | 2319 | struct neigh_seq_state *state = seq->private; |
2198 | struct net *net = seq_file_net(seq); | 2320 | struct net *net = seq_file_net(seq); |
2199 | struct neigh_table *tbl = state->tbl; | 2321 | struct neigh_hash_table *nht = state->nht; |
2200 | struct neighbour *n = NULL; | 2322 | struct neighbour *n = NULL; |
2201 | int bucket = state->bucket; | 2323 | int bucket = state->bucket; |
2202 | 2324 | ||
2203 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; | 2325 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; |
2204 | for (bucket = 0; bucket <= tbl->hash_mask; bucket++) { | 2326 | for (bucket = 0; bucket <= nht->hash_mask; bucket++) { |
2205 | n = tbl->hash_buckets[bucket]; | 2327 | n = rcu_dereference_bh(nht->hash_buckets[bucket]); |
2206 | 2328 | ||
2207 | while (n) { | 2329 | while (n) { |
2208 | if (!net_eq(dev_net(n->dev), net)) | 2330 | if (!net_eq(dev_net(n->dev), net)) |
@@ -2219,8 +2341,8 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
2219 | break; | 2341 | break; |
2220 | if (n->nud_state & ~NUD_NOARP) | 2342 | if (n->nud_state & ~NUD_NOARP) |
2221 | break; | 2343 | break; |
2222 | next: | 2344 | next: |
2223 | n = n->next; | 2345 | n = rcu_dereference_bh(n->next); |
2224 | } | 2346 | } |
2225 | 2347 | ||
2226 | if (n) | 2348 | if (n) |
@@ -2237,14 +2359,14 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2237 | { | 2359 | { |
2238 | struct neigh_seq_state *state = seq->private; | 2360 | struct neigh_seq_state *state = seq->private; |
2239 | struct net *net = seq_file_net(seq); | 2361 | struct net *net = seq_file_net(seq); |
2240 | struct neigh_table *tbl = state->tbl; | 2362 | struct neigh_hash_table *nht = state->nht; |
2241 | 2363 | ||
2242 | if (state->neigh_sub_iter) { | 2364 | if (state->neigh_sub_iter) { |
2243 | void *v = state->neigh_sub_iter(state, n, pos); | 2365 | void *v = state->neigh_sub_iter(state, n, pos); |
2244 | if (v) | 2366 | if (v) |
2245 | return n; | 2367 | return n; |
2246 | } | 2368 | } |
2247 | n = n->next; | 2369 | n = rcu_dereference_bh(n->next); |
2248 | 2370 | ||
2249 | while (1) { | 2371 | while (1) { |
2250 | while (n) { | 2372 | while (n) { |
@@ -2261,17 +2383,17 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2261 | 2383 | ||
2262 | if (n->nud_state & ~NUD_NOARP) | 2384 | if (n->nud_state & ~NUD_NOARP) |
2263 | break; | 2385 | break; |
2264 | next: | 2386 | next: |
2265 | n = n->next; | 2387 | n = rcu_dereference_bh(n->next); |
2266 | } | 2388 | } |
2267 | 2389 | ||
2268 | if (n) | 2390 | if (n) |
2269 | break; | 2391 | break; |
2270 | 2392 | ||
2271 | if (++state->bucket > tbl->hash_mask) | 2393 | if (++state->bucket > nht->hash_mask) |
2272 | break; | 2394 | break; |
2273 | 2395 | ||
2274 | n = tbl->hash_buckets[state->bucket]; | 2396 | n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); |
2275 | } | 2397 | } |
2276 | 2398 | ||
2277 | if (n && pos) | 2399 | if (n && pos) |
@@ -2369,7 +2491,7 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos) | |||
2369 | } | 2491 | } |
2370 | 2492 | ||
2371 | void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags) | 2493 | void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags) |
2372 | __acquires(tbl->lock) | 2494 | __acquires(rcu_bh) |
2373 | { | 2495 | { |
2374 | struct neigh_seq_state *state = seq->private; | 2496 | struct neigh_seq_state *state = seq->private; |
2375 | 2497 | ||
@@ -2377,7 +2499,8 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl | |||
2377 | state->bucket = 0; | 2499 | state->bucket = 0; |
2378 | state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH); | 2500 | state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH); |
2379 | 2501 | ||
2380 | read_lock_bh(&tbl->lock); | 2502 | rcu_read_lock_bh(); |
2503 | state->nht = rcu_dereference_bh(tbl->nht); | ||
2381 | 2504 | ||
2382 | return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN; | 2505 | return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN; |
2383 | } | 2506 | } |
@@ -2411,12 +2534,9 @@ out: | |||
2411 | EXPORT_SYMBOL(neigh_seq_next); | 2534 | EXPORT_SYMBOL(neigh_seq_next); |
2412 | 2535 | ||
2413 | void neigh_seq_stop(struct seq_file *seq, void *v) | 2536 | void neigh_seq_stop(struct seq_file *seq, void *v) |
2414 | __releases(tbl->lock) | 2537 | __releases(rcu_bh) |
2415 | { | 2538 | { |
2416 | struct neigh_seq_state *state = seq->private; | 2539 | rcu_read_unlock_bh(); |
2417 | struct neigh_table *tbl = state->tbl; | ||
2418 | |||
2419 | read_unlock_bh(&tbl->lock); | ||
2420 | } | 2540 | } |
2421 | EXPORT_SYMBOL(neigh_seq_stop); | 2541 | EXPORT_SYMBOL(neigh_seq_stop); |
2422 | 2542 | ||