diff options
Diffstat (limited to 'net/core/neighbour.c')
| -rw-r--r-- | net/core/neighbour.c | 191 |
1 files changed, 64 insertions, 127 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 799f06e03a22..8fab9b0bb203 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops; | |||
| 98 | 98 | ||
| 99 | static DEFINE_RWLOCK(neigh_tbl_lock); | 99 | static DEFINE_RWLOCK(neigh_tbl_lock); |
| 100 | 100 | ||
| 101 | static int neigh_blackhole(struct sk_buff *skb) | 101 | static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb) |
| 102 | { | 102 | { |
| 103 | kfree_skb(skb); | 103 | kfree_skb(skb); |
| 104 | return -ENETDOWN; | 104 | return -ENETDOWN; |
| @@ -137,7 +137,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
| 137 | write_lock_bh(&tbl->lock); | 137 | write_lock_bh(&tbl->lock); |
| 138 | nht = rcu_dereference_protected(tbl->nht, | 138 | nht = rcu_dereference_protected(tbl->nht, |
| 139 | lockdep_is_held(&tbl->lock)); | 139 | lockdep_is_held(&tbl->lock)); |
| 140 | for (i = 0; i <= nht->hash_mask; i++) { | 140 | for (i = 0; i < (1 << nht->hash_shift); i++) { |
| 141 | struct neighbour *n; | 141 | struct neighbour *n; |
| 142 | struct neighbour __rcu **np; | 142 | struct neighbour __rcu **np; |
| 143 | 143 | ||
| @@ -210,7 +210,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | |||
| 210 | nht = rcu_dereference_protected(tbl->nht, | 210 | nht = rcu_dereference_protected(tbl->nht, |
| 211 | lockdep_is_held(&tbl->lock)); | 211 | lockdep_is_held(&tbl->lock)); |
| 212 | 212 | ||
| 213 | for (i = 0; i <= nht->hash_mask; i++) { | 213 | for (i = 0; i < (1 << nht->hash_shift); i++) { |
| 214 | struct neighbour *n; | 214 | struct neighbour *n; |
| 215 | struct neighbour __rcu **np = &nht->hash_buckets[i]; | 215 | struct neighbour __rcu **np = &nht->hash_buckets[i]; |
| 216 | 216 | ||
| @@ -297,6 +297,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl) | |||
| 297 | n->updated = n->used = now; | 297 | n->updated = n->used = now; |
| 298 | n->nud_state = NUD_NONE; | 298 | n->nud_state = NUD_NONE; |
| 299 | n->output = neigh_blackhole; | 299 | n->output = neigh_blackhole; |
| 300 | seqlock_init(&n->hh.hh_lock); | ||
| 300 | n->parms = neigh_parms_clone(&tbl->parms); | 301 | n->parms = neigh_parms_clone(&tbl->parms); |
| 301 | setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); | 302 | setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); |
| 302 | 303 | ||
| @@ -312,9 +313,9 @@ out_entries: | |||
| 312 | goto out; | 313 | goto out; |
| 313 | } | 314 | } |
| 314 | 315 | ||
| 315 | static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries) | 316 | static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift) |
| 316 | { | 317 | { |
| 317 | size_t size = entries * sizeof(struct neighbour *); | 318 | size_t size = (1 << shift) * sizeof(struct neighbour *); |
| 318 | struct neigh_hash_table *ret; | 319 | struct neigh_hash_table *ret; |
| 319 | struct neighbour __rcu **buckets; | 320 | struct neighbour __rcu **buckets; |
| 320 | 321 | ||
| @@ -332,8 +333,9 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries) | |||
| 332 | return NULL; | 333 | return NULL; |
| 333 | } | 334 | } |
| 334 | ret->hash_buckets = buckets; | 335 | ret->hash_buckets = buckets; |
| 335 | ret->hash_mask = entries - 1; | 336 | ret->hash_shift = shift; |
| 336 | get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd)); | 337 | get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd)); |
| 338 | ret->hash_rnd |= 1; | ||
| 337 | return ret; | 339 | return ret; |
| 338 | } | 340 | } |
| 339 | 341 | ||
| @@ -342,7 +344,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head) | |||
| 342 | struct neigh_hash_table *nht = container_of(head, | 344 | struct neigh_hash_table *nht = container_of(head, |
| 343 | struct neigh_hash_table, | 345 | struct neigh_hash_table, |
| 344 | rcu); | 346 | rcu); |
| 345 | size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *); | 347 | size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *); |
| 346 | struct neighbour __rcu **buckets = nht->hash_buckets; | 348 | struct neighbour __rcu **buckets = nht->hash_buckets; |
| 347 | 349 | ||
| 348 | if (size <= PAGE_SIZE) | 350 | if (size <= PAGE_SIZE) |
| @@ -353,21 +355,20 @@ static void neigh_hash_free_rcu(struct rcu_head *head) | |||
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, | 357 | static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, |
| 356 | unsigned long new_entries) | 358 | unsigned long new_shift) |
| 357 | { | 359 | { |
| 358 | unsigned int i, hash; | 360 | unsigned int i, hash; |
| 359 | struct neigh_hash_table *new_nht, *old_nht; | 361 | struct neigh_hash_table *new_nht, *old_nht; |
| 360 | 362 | ||
| 361 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); | 363 | NEIGH_CACHE_STAT_INC(tbl, hash_grows); |
| 362 | 364 | ||
| 363 | BUG_ON(!is_power_of_2(new_entries)); | ||
| 364 | old_nht = rcu_dereference_protected(tbl->nht, | 365 | old_nht = rcu_dereference_protected(tbl->nht, |
| 365 | lockdep_is_held(&tbl->lock)); | 366 | lockdep_is_held(&tbl->lock)); |
| 366 | new_nht = neigh_hash_alloc(new_entries); | 367 | new_nht = neigh_hash_alloc(new_shift); |
| 367 | if (!new_nht) | 368 | if (!new_nht) |
| 368 | return old_nht; | 369 | return old_nht; |
| 369 | 370 | ||
| 370 | for (i = 0; i <= old_nht->hash_mask; i++) { | 371 | for (i = 0; i < (1 << old_nht->hash_shift); i++) { |
| 371 | struct neighbour *n, *next; | 372 | struct neighbour *n, *next; |
| 372 | 373 | ||
| 373 | for (n = rcu_dereference_protected(old_nht->hash_buckets[i], | 374 | for (n = rcu_dereference_protected(old_nht->hash_buckets[i], |
| @@ -377,7 +378,7 @@ static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, | |||
| 377 | hash = tbl->hash(n->primary_key, n->dev, | 378 | hash = tbl->hash(n->primary_key, n->dev, |
| 378 | new_nht->hash_rnd); | 379 | new_nht->hash_rnd); |
| 379 | 380 | ||
| 380 | hash &= new_nht->hash_mask; | 381 | hash >>= (32 - new_nht->hash_shift); |
| 381 | next = rcu_dereference_protected(n->next, | 382 | next = rcu_dereference_protected(n->next, |
| 382 | lockdep_is_held(&tbl->lock)); | 383 | lockdep_is_held(&tbl->lock)); |
| 383 | 384 | ||
| @@ -406,7 +407,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
| 406 | 407 | ||
| 407 | rcu_read_lock_bh(); | 408 | rcu_read_lock_bh(); |
| 408 | nht = rcu_dereference_bh(tbl->nht); | 409 | nht = rcu_dereference_bh(tbl->nht); |
| 409 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; | 410 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 410 | 411 | ||
| 411 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | 412 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); |
| 412 | n != NULL; | 413 | n != NULL; |
| @@ -436,7 +437,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, | |||
| 436 | 437 | ||
| 437 | rcu_read_lock_bh(); | 438 | rcu_read_lock_bh(); |
| 438 | nht = rcu_dereference_bh(tbl->nht); | 439 | nht = rcu_dereference_bh(tbl->nht); |
| 439 | hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) & nht->hash_mask; | 440 | hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 440 | 441 | ||
| 441 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); | 442 | for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); |
| 442 | n != NULL; | 443 | n != NULL; |
| @@ -492,10 +493,10 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, | |||
| 492 | nht = rcu_dereference_protected(tbl->nht, | 493 | nht = rcu_dereference_protected(tbl->nht, |
| 493 | lockdep_is_held(&tbl->lock)); | 494 | lockdep_is_held(&tbl->lock)); |
| 494 | 495 | ||
| 495 | if (atomic_read(&tbl->entries) > (nht->hash_mask + 1)) | 496 | if (atomic_read(&tbl->entries) > (1 << nht->hash_shift)) |
| 496 | nht = neigh_hash_grow(tbl, (nht->hash_mask + 1) << 1); | 497 | nht = neigh_hash_grow(tbl, nht->hash_shift + 1); |
| 497 | 498 | ||
| 498 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) & nht->hash_mask; | 499 | hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); |
| 499 | 500 | ||
| 500 | if (n->parms->dead) { | 501 | if (n->parms->dead) { |
| 501 | rc = ERR_PTR(-EINVAL); | 502 | rc = ERR_PTR(-EINVAL); |
| @@ -688,8 +689,6 @@ static void neigh_destroy_rcu(struct rcu_head *head) | |||
| 688 | */ | 689 | */ |
| 689 | void neigh_destroy(struct neighbour *neigh) | 690 | void neigh_destroy(struct neighbour *neigh) |
| 690 | { | 691 | { |
| 691 | struct hh_cache *hh; | ||
| 692 | |||
| 693 | NEIGH_CACHE_STAT_INC(neigh->tbl, destroys); | 692 | NEIGH_CACHE_STAT_INC(neigh->tbl, destroys); |
| 694 | 693 | ||
| 695 | if (!neigh->dead) { | 694 | if (!neigh->dead) { |
| @@ -702,16 +701,6 @@ void neigh_destroy(struct neighbour *neigh) | |||
| 702 | if (neigh_del_timer(neigh)) | 701 | if (neigh_del_timer(neigh)) |
| 703 | printk(KERN_WARNING "Impossible event.\n"); | 702 | printk(KERN_WARNING "Impossible event.\n"); |
| 704 | 703 | ||
| 705 | while ((hh = neigh->hh) != NULL) { | ||
| 706 | neigh->hh = hh->hh_next; | ||
| 707 | hh->hh_next = NULL; | ||
| 708 | |||
| 709 | write_seqlock_bh(&hh->hh_lock); | ||
| 710 | hh->hh_output = neigh_blackhole; | ||
| 711 | write_sequnlock_bh(&hh->hh_lock); | ||
| 712 | hh_cache_put(hh); | ||
| 713 | } | ||
| 714 | |||
| 715 | skb_queue_purge(&neigh->arp_queue); | 704 | skb_queue_purge(&neigh->arp_queue); |
| 716 | 705 | ||
| 717 | dev_put(neigh->dev); | 706 | dev_put(neigh->dev); |
| @@ -731,14 +720,9 @@ EXPORT_SYMBOL(neigh_destroy); | |||
| 731 | */ | 720 | */ |
| 732 | static void neigh_suspect(struct neighbour *neigh) | 721 | static void neigh_suspect(struct neighbour *neigh) |
| 733 | { | 722 | { |
| 734 | struct hh_cache *hh; | ||
| 735 | |||
| 736 | NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); | 723 | NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); |
| 737 | 724 | ||
| 738 | neigh->output = neigh->ops->output; | 725 | neigh->output = neigh->ops->output; |
| 739 | |||
| 740 | for (hh = neigh->hh; hh; hh = hh->hh_next) | ||
| 741 | hh->hh_output = neigh->ops->output; | ||
| 742 | } | 726 | } |
| 743 | 727 | ||
| 744 | /* Neighbour state is OK; | 728 | /* Neighbour state is OK; |
| @@ -748,14 +732,9 @@ static void neigh_suspect(struct neighbour *neigh) | |||
| 748 | */ | 732 | */ |
| 749 | static void neigh_connect(struct neighbour *neigh) | 733 | static void neigh_connect(struct neighbour *neigh) |
| 750 | { | 734 | { |
| 751 | struct hh_cache *hh; | ||
| 752 | |||
| 753 | NEIGH_PRINTK2("neigh %p is connected.\n", neigh); | 735 | NEIGH_PRINTK2("neigh %p is connected.\n", neigh); |
| 754 | 736 | ||
| 755 | neigh->output = neigh->ops->connected_output; | 737 | neigh->output = neigh->ops->connected_output; |
| 756 | |||
| 757 | for (hh = neigh->hh; hh; hh = hh->hh_next) | ||
| 758 | hh->hh_output = neigh->ops->hh_output; | ||
| 759 | } | 738 | } |
| 760 | 739 | ||
| 761 | static void neigh_periodic_work(struct work_struct *work) | 740 | static void neigh_periodic_work(struct work_struct *work) |
| @@ -784,7 +763,7 @@ static void neigh_periodic_work(struct work_struct *work) | |||
| 784 | neigh_rand_reach_time(p->base_reachable_time); | 763 | neigh_rand_reach_time(p->base_reachable_time); |
| 785 | } | 764 | } |
| 786 | 765 | ||
| 787 | for (i = 0 ; i <= nht->hash_mask; i++) { | 766 | for (i = 0 ; i < (1 << nht->hash_shift); i++) { |
| 788 | np = &nht->hash_buckets[i]; | 767 | np = &nht->hash_buckets[i]; |
| 789 | 768 | ||
| 790 | while ((n = rcu_dereference_protected(*np, | 769 | while ((n = rcu_dereference_protected(*np, |
| @@ -1015,7 +994,7 @@ out_unlock_bh: | |||
| 1015 | } | 994 | } |
| 1016 | EXPORT_SYMBOL(__neigh_event_send); | 995 | EXPORT_SYMBOL(__neigh_event_send); |
| 1017 | 996 | ||
| 1018 | static void neigh_update_hhs(const struct neighbour *neigh) | 997 | static void neigh_update_hhs(struct neighbour *neigh) |
| 1019 | { | 998 | { |
| 1020 | struct hh_cache *hh; | 999 | struct hh_cache *hh; |
| 1021 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) | 1000 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) |
| @@ -1025,7 +1004,8 @@ static void neigh_update_hhs(const struct neighbour *neigh) | |||
| 1025 | update = neigh->dev->header_ops->cache_update; | 1004 | update = neigh->dev->header_ops->cache_update; |
| 1026 | 1005 | ||
| 1027 | if (update) { | 1006 | if (update) { |
| 1028 | for (hh = neigh->hh; hh; hh = hh->hh_next) { | 1007 | hh = &neigh->hh; |
| 1008 | if (hh->hh_len) { | ||
| 1029 | write_seqlock_bh(&hh->hh_lock); | 1009 | write_seqlock_bh(&hh->hh_lock); |
| 1030 | update(hh, neigh->dev, neigh->ha); | 1010 | update(hh, neigh->dev, neigh->ha); |
| 1031 | write_sequnlock_bh(&hh->hh_lock); | 1011 | write_sequnlock_bh(&hh->hh_lock); |
| @@ -1173,12 +1153,13 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
| 1173 | 1153 | ||
| 1174 | while (neigh->nud_state & NUD_VALID && | 1154 | while (neigh->nud_state & NUD_VALID && |
| 1175 | (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { | 1155 | (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) { |
| 1176 | struct neighbour *n1 = neigh; | 1156 | struct dst_entry *dst = skb_dst(skb); |
| 1157 | struct neighbour *n2, *n1 = neigh; | ||
| 1177 | write_unlock_bh(&neigh->lock); | 1158 | write_unlock_bh(&neigh->lock); |
| 1178 | /* On shaper/eql skb->dst->neighbour != neigh :( */ | 1159 | /* On shaper/eql skb->dst->neighbour != neigh :( */ |
| 1179 | if (skb_dst(skb) && skb_dst(skb)->neighbour) | 1160 | if (dst && (n2 = dst_get_neighbour(dst)) != NULL) |
| 1180 | n1 = skb_dst(skb)->neighbour; | 1161 | n1 = n2; |
| 1181 | n1->output(skb); | 1162 | n1->output(n1, skb); |
| 1182 | write_lock_bh(&neigh->lock); | 1163 | write_lock_bh(&neigh->lock); |
| 1183 | } | 1164 | } |
| 1184 | skb_queue_purge(&neigh->arp_queue); | 1165 | skb_queue_purge(&neigh->arp_queue); |
| @@ -1211,67 +1192,21 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
| 1211 | } | 1192 | } |
| 1212 | EXPORT_SYMBOL(neigh_event_ns); | 1193 | EXPORT_SYMBOL(neigh_event_ns); |
| 1213 | 1194 | ||
| 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); */ | 1195 | /* called with read_lock_bh(&n->lock); */ |
| 1232 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, | 1196 | static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst) |
| 1233 | __be16 protocol) | ||
| 1234 | { | 1197 | { |
| 1235 | struct hh_cache *hh; | ||
| 1236 | struct net_device *dev = dst->dev; | 1198 | struct net_device *dev = dst->dev; |
| 1237 | 1199 | __be16 prot = dst->ops->protocol; | |
| 1238 | if (likely(neigh_hh_lookup(n, dst, protocol))) | 1200 | struct hh_cache *hh = &n->hh; |
| 1239 | return; | ||
| 1240 | |||
| 1241 | /* slow path */ | ||
| 1242 | hh = kzalloc(sizeof(*hh), GFP_ATOMIC); | ||
| 1243 | if (!hh) | ||
| 1244 | return; | ||
| 1245 | |||
| 1246 | seqlock_init(&hh->hh_lock); | ||
| 1247 | hh->hh_type = protocol; | ||
| 1248 | atomic_set(&hh->hh_refcnt, 2); | ||
| 1249 | |||
| 1250 | if (dev->header_ops->cache(n, hh)) { | ||
| 1251 | kfree(hh); | ||
| 1252 | return; | ||
| 1253 | } | ||
| 1254 | 1201 | ||
| 1255 | write_lock_bh(&n->lock); | 1202 | write_lock_bh(&n->lock); |
| 1256 | 1203 | ||
| 1257 | /* must check if another thread already did the insert */ | 1204 | /* Only one thread can come in here and initialize the |
| 1258 | if (neigh_hh_lookup(n, dst, protocol)) { | 1205 | * hh_cache entry. |
| 1259 | kfree(hh); | 1206 | */ |
| 1260 | goto end; | 1207 | if (!hh->hh_len) |
| 1261 | } | 1208 | dev->header_ops->cache(n, hh, prot); |
| 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 | 1209 | ||
| 1272 | if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) | ||
| 1273 | hh_cache_put(hh); | ||
| 1274 | end: | ||
| 1275 | write_unlock_bh(&n->lock); | 1210 | write_unlock_bh(&n->lock); |
| 1276 | } | 1211 | } |
| 1277 | 1212 | ||
| @@ -1280,7 +1215,7 @@ end: | |||
| 1280 | * but resolution is not made yet. | 1215 | * but resolution is not made yet. |
| 1281 | */ | 1216 | */ |
| 1282 | 1217 | ||
| 1283 | int neigh_compat_output(struct sk_buff *skb) | 1218 | int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1284 | { | 1219 | { |
| 1285 | struct net_device *dev = skb->dev; | 1220 | struct net_device *dev = skb->dev; |
| 1286 | 1221 | ||
| @@ -1297,13 +1232,12 @@ EXPORT_SYMBOL(neigh_compat_output); | |||
| 1297 | 1232 | ||
| 1298 | /* Slow and careful. */ | 1233 | /* Slow and careful. */ |
| 1299 | 1234 | ||
| 1300 | int neigh_resolve_output(struct sk_buff *skb) | 1235 | int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1301 | { | 1236 | { |
| 1302 | struct dst_entry *dst = skb_dst(skb); | 1237 | struct dst_entry *dst = skb_dst(skb); |
| 1303 | struct neighbour *neigh; | ||
| 1304 | int rc = 0; | 1238 | int rc = 0; |
| 1305 | 1239 | ||
| 1306 | if (!dst || !(neigh = dst->neighbour)) | 1240 | if (!dst) |
| 1307 | goto discard; | 1241 | goto discard; |
| 1308 | 1242 | ||
| 1309 | __skb_pull(skb, skb_network_offset(skb)); | 1243 | __skb_pull(skb, skb_network_offset(skb)); |
| @@ -1313,10 +1247,8 @@ int neigh_resolve_output(struct sk_buff *skb) | |||
| 1313 | struct net_device *dev = neigh->dev; | 1247 | struct net_device *dev = neigh->dev; |
| 1314 | unsigned int seq; | 1248 | unsigned int seq; |
| 1315 | 1249 | ||
| 1316 | if (dev->header_ops->cache && | 1250 | if (dev->header_ops->cache && !neigh->hh.hh_len) |
| 1317 | !dst->hh && | 1251 | neigh_hh_init(neigh, dst); |
| 1318 | !(dst->flags & DST_NOCACHE)) | ||
| 1319 | neigh_hh_init(neigh, dst, dst->ops->protocol); | ||
| 1320 | 1252 | ||
| 1321 | do { | 1253 | do { |
| 1322 | seq = read_seqbegin(&neigh->ha_lock); | 1254 | seq = read_seqbegin(&neigh->ha_lock); |
| @@ -1325,7 +1257,7 @@ int neigh_resolve_output(struct sk_buff *skb) | |||
| 1325 | } while (read_seqretry(&neigh->ha_lock, seq)); | 1257 | } while (read_seqretry(&neigh->ha_lock, seq)); |
| 1326 | 1258 | ||
| 1327 | if (err >= 0) | 1259 | if (err >= 0) |
| 1328 | rc = neigh->ops->queue_xmit(skb); | 1260 | rc = dev_queue_xmit(skb); |
| 1329 | else | 1261 | else |
| 1330 | goto out_kfree_skb; | 1262 | goto out_kfree_skb; |
| 1331 | } | 1263 | } |
| @@ -1333,7 +1265,7 @@ out: | |||
| 1333 | return rc; | 1265 | return rc; |
| 1334 | discard: | 1266 | discard: |
| 1335 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", | 1267 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", |
| 1336 | dst, dst ? dst->neighbour : NULL); | 1268 | dst, neigh); |
| 1337 | out_kfree_skb: | 1269 | out_kfree_skb: |
| 1338 | rc = -EINVAL; | 1270 | rc = -EINVAL; |
| 1339 | kfree_skb(skb); | 1271 | kfree_skb(skb); |
| @@ -1343,13 +1275,11 @@ EXPORT_SYMBOL(neigh_resolve_output); | |||
| 1343 | 1275 | ||
| 1344 | /* As fast as possible without hh cache */ | 1276 | /* As fast as possible without hh cache */ |
| 1345 | 1277 | ||
| 1346 | int neigh_connected_output(struct sk_buff *skb) | 1278 | int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) |
| 1347 | { | 1279 | { |
| 1348 | int err; | ||
| 1349 | struct dst_entry *dst = skb_dst(skb); | ||
| 1350 | struct neighbour *neigh = dst->neighbour; | ||
| 1351 | struct net_device *dev = neigh->dev; | 1280 | struct net_device *dev = neigh->dev; |
| 1352 | unsigned int seq; | 1281 | unsigned int seq; |
| 1282 | int err; | ||
| 1353 | 1283 | ||
| 1354 | __skb_pull(skb, skb_network_offset(skb)); | 1284 | __skb_pull(skb, skb_network_offset(skb)); |
| 1355 | 1285 | ||
| @@ -1360,7 +1290,7 @@ int neigh_connected_output(struct sk_buff *skb) | |||
| 1360 | } while (read_seqretry(&neigh->ha_lock, seq)); | 1290 | } while (read_seqretry(&neigh->ha_lock, seq)); |
| 1361 | 1291 | ||
| 1362 | if (err >= 0) | 1292 | if (err >= 0) |
| 1363 | err = neigh->ops->queue_xmit(skb); | 1293 | err = dev_queue_xmit(skb); |
| 1364 | else { | 1294 | else { |
| 1365 | err = -EINVAL; | 1295 | err = -EINVAL; |
| 1366 | kfree_skb(skb); | 1296 | kfree_skb(skb); |
| @@ -1369,6 +1299,12 @@ int neigh_connected_output(struct sk_buff *skb) | |||
| 1369 | } | 1299 | } |
| 1370 | EXPORT_SYMBOL(neigh_connected_output); | 1300 | EXPORT_SYMBOL(neigh_connected_output); |
| 1371 | 1301 | ||
| 1302 | int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb) | ||
| 1303 | { | ||
| 1304 | return dev_queue_xmit(skb); | ||
| 1305 | } | ||
| 1306 | EXPORT_SYMBOL(neigh_direct_output); | ||
| 1307 | |||
| 1372 | static void neigh_proxy_process(unsigned long arg) | 1308 | static void neigh_proxy_process(unsigned long arg) |
| 1373 | { | 1309 | { |
| 1374 | struct neigh_table *tbl = (struct neigh_table *)arg; | 1310 | struct neigh_table *tbl = (struct neigh_table *)arg; |
| @@ -1540,7 +1476,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
| 1540 | panic("cannot create neighbour proc dir entry"); | 1476 | panic("cannot create neighbour proc dir entry"); |
| 1541 | #endif | 1477 | #endif |
| 1542 | 1478 | ||
| 1543 | RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8)); | 1479 | RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3)); |
| 1544 | 1480 | ||
| 1545 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); | 1481 | phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); |
| 1546 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); | 1482 | tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); |
| @@ -1857,7 +1793,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |||
| 1857 | rcu_read_lock_bh(); | 1793 | rcu_read_lock_bh(); |
| 1858 | nht = rcu_dereference_bh(tbl->nht); | 1794 | nht = rcu_dereference_bh(tbl->nht); |
| 1859 | ndc.ndtc_hash_rnd = nht->hash_rnd; | 1795 | ndc.ndtc_hash_rnd = nht->hash_rnd; |
| 1860 | ndc.ndtc_hash_mask = nht->hash_mask; | 1796 | ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1); |
| 1861 | rcu_read_unlock_bh(); | 1797 | rcu_read_unlock_bh(); |
| 1862 | 1798 | ||
| 1863 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); | 1799 | NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); |
| @@ -2200,7 +2136,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 2200 | rcu_read_lock_bh(); | 2136 | rcu_read_lock_bh(); |
| 2201 | nht = rcu_dereference_bh(tbl->nht); | 2137 | nht = rcu_dereference_bh(tbl->nht); |
| 2202 | 2138 | ||
| 2203 | for (h = 0; h <= nht->hash_mask; h++) { | 2139 | for (h = 0; h < (1 << nht->hash_shift); h++) { |
| 2204 | if (h < s_h) | 2140 | if (h < s_h) |
| 2205 | continue; | 2141 | continue; |
| 2206 | if (h > s_h) | 2142 | if (h > s_h) |
| @@ -2264,7 +2200,7 @@ void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void | |||
| 2264 | nht = rcu_dereference_bh(tbl->nht); | 2200 | nht = rcu_dereference_bh(tbl->nht); |
| 2265 | 2201 | ||
| 2266 | read_lock(&tbl->lock); /* avoid resizes */ | 2202 | read_lock(&tbl->lock); /* avoid resizes */ |
| 2267 | for (chain = 0; chain <= nht->hash_mask; chain++) { | 2203 | for (chain = 0; chain < (1 << nht->hash_shift); chain++) { |
| 2268 | struct neighbour *n; | 2204 | struct neighbour *n; |
| 2269 | 2205 | ||
| 2270 | for (n = rcu_dereference_bh(nht->hash_buckets[chain]); | 2206 | for (n = rcu_dereference_bh(nht->hash_buckets[chain]); |
| @@ -2286,7 +2222,7 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
| 2286 | 2222 | ||
| 2287 | nht = rcu_dereference_protected(tbl->nht, | 2223 | nht = rcu_dereference_protected(tbl->nht, |
| 2288 | lockdep_is_held(&tbl->lock)); | 2224 | lockdep_is_held(&tbl->lock)); |
| 2289 | for (chain = 0; chain <= nht->hash_mask; chain++) { | 2225 | for (chain = 0; chain < (1 << nht->hash_shift); chain++) { |
| 2290 | struct neighbour *n; | 2226 | struct neighbour *n; |
| 2291 | struct neighbour __rcu **np; | 2227 | struct neighbour __rcu **np; |
| 2292 | 2228 | ||
| @@ -2323,7 +2259,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
| 2323 | int bucket = state->bucket; | 2259 | int bucket = state->bucket; |
| 2324 | 2260 | ||
| 2325 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; | 2261 | state->flags &= ~NEIGH_SEQ_IS_PNEIGH; |
| 2326 | for (bucket = 0; bucket <= nht->hash_mask; bucket++) { | 2262 | for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) { |
| 2327 | n = rcu_dereference_bh(nht->hash_buckets[bucket]); | 2263 | n = rcu_dereference_bh(nht->hash_buckets[bucket]); |
| 2328 | 2264 | ||
| 2329 | while (n) { | 2265 | while (n) { |
| @@ -2390,7 +2326,7 @@ next: | |||
| 2390 | if (n) | 2326 | if (n) |
| 2391 | break; | 2327 | break; |
| 2392 | 2328 | ||
| 2393 | if (++state->bucket > nht->hash_mask) | 2329 | if (++state->bucket >= (1 << nht->hash_shift)) |
| 2394 | break; | 2330 | break; |
| 2395 | 2331 | ||
| 2396 | n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); | 2332 | n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); |
| @@ -2909,12 +2845,13 @@ EXPORT_SYMBOL(neigh_sysctl_unregister); | |||
| 2909 | 2845 | ||
| 2910 | static int __init neigh_init(void) | 2846 | static int __init neigh_init(void) |
| 2911 | { | 2847 | { |
| 2912 | rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL); | 2848 | rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL); |
| 2913 | rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL); | 2849 | rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL); |
| 2914 | rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info); | 2850 | rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL); |
| 2915 | 2851 | ||
| 2916 | rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info); | 2852 | rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info, |
| 2917 | rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL); | 2853 | NULL); |
| 2854 | rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL); | ||
| 2918 | 2855 | ||
| 2919 | return 0; | 2856 | return 0; |
| 2920 | } | 2857 | } |
