aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-13 03:51:10 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-13 05:29:59 -0400
commit5c25f686db352082eef8daa21b760192351a023a (patch)
tree20b1d6797b0d9d6757e2e367ceb6cc4fe866acbe /net/core
parente69dd336ee3a05a589629b505b18ba5e7a5b4c54 (diff)
net: Kill support for multiple hh_cache entries per neighbour
This never, ever, happens. Neighbour entries are always tied to one address family, and therefore one set of dst_ops, and therefore one dst_ops->protocol "hh_type" value. This capability was blindly imported by Alexey Kuznetsov when he wrote the neighbour layer. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/neighbour.c37
1 files changed, 18 insertions, 19 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 8f7e1d8d92a..f879bb55299 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -702,9 +702,9 @@ void neigh_destroy(struct neighbour *neigh)
702 if (neigh_del_timer(neigh)) 702 if (neigh_del_timer(neigh))
703 printk(KERN_WARNING "Impossible event.\n"); 703 printk(KERN_WARNING "Impossible event.\n");
704 704
705 while ((hh = neigh->hh) != NULL) { 705 hh = neigh->hh;
706 neigh->hh = hh->hh_next; 706 if (hh) {
707 hh->hh_next = NULL; 707 neigh->hh = NULL;
708 708
709 write_seqlock_bh(&hh->hh_lock); 709 write_seqlock_bh(&hh->hh_lock);
710 hh->hh_output = neigh_blackhole; 710 hh->hh_output = neigh_blackhole;
@@ -737,7 +737,8 @@ static void neigh_suspect(struct neighbour *neigh)
737 737
738 neigh->output = neigh->ops->output; 738 neigh->output = neigh->ops->output;
739 739
740 for (hh = neigh->hh; hh; hh = hh->hh_next) 740 hh = neigh->hh;
741 if (hh)
741 hh->hh_output = neigh->ops->output; 742 hh->hh_output = neigh->ops->output;
742} 743}
743 744
@@ -754,7 +755,8 @@ static void neigh_connect(struct neighbour *neigh)
754 755
755 neigh->output = neigh->ops->connected_output; 756 neigh->output = neigh->ops->connected_output;
756 757
757 for (hh = neigh->hh; hh; hh = hh->hh_next) 758 hh = neigh->hh;
759 if (hh)
758 hh->hh_output = neigh->ops->hh_output; 760 hh->hh_output = neigh->ops->hh_output;
759} 761}
760 762
@@ -1025,7 +1027,8 @@ static void neigh_update_hhs(const struct neighbour *neigh)
1025 update = neigh->dev->header_ops->cache_update; 1027 update = neigh->dev->header_ops->cache_update;
1026 1028
1027 if (update) { 1029 if (update) {
1028 for (hh = neigh->hh; hh; hh = hh->hh_next) { 1030 hh = neigh->hh;
1031 if (hh) {
1029 write_seqlock_bh(&hh->hh_lock); 1032 write_seqlock_bh(&hh->hh_lock);
1030 update(hh, neigh->dev, neigh->ha); 1033 update(hh, neigh->dev, neigh->ha);
1031 write_sequnlock_bh(&hh->hh_lock); 1034 write_sequnlock_bh(&hh->hh_lock);
@@ -1211,19 +1214,17 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1211} 1214}
1212EXPORT_SYMBOL(neigh_event_ns); 1215EXPORT_SYMBOL(neigh_event_ns);
1213 1216
1214static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst, 1217static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst)
1215 __be16 protocol)
1216{ 1218{
1217 struct hh_cache *hh; 1219 struct hh_cache *hh;
1218 1220
1219 smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */ 1221 smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */
1220 for (hh = n->hh; hh; hh = hh->hh_next) { 1222 hh = n->hh;
1221 if (hh->hh_type == protocol) { 1223 if (hh) {
1222 atomic_inc(&hh->hh_refcnt); 1224 atomic_inc(&hh->hh_refcnt);
1223 if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) 1225 if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
1224 hh_cache_put(hh); 1226 hh_cache_put(hh);
1225 return true; 1227 return true;
1226 }
1227 } 1228 }
1228 return false; 1229 return false;
1229} 1230}
@@ -1235,7 +1236,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1235 struct hh_cache *hh; 1236 struct hh_cache *hh;
1236 struct net_device *dev = dst->dev; 1237 struct net_device *dev = dst->dev;
1237 1238
1238 if (likely(neigh_hh_lookup(n, dst, protocol))) 1239 if (likely(neigh_hh_lookup(n, dst)))
1239 return; 1240 return;
1240 1241
1241 /* slow path */ 1242 /* slow path */
@@ -1244,7 +1245,6 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1244 return; 1245 return;
1245 1246
1246 seqlock_init(&hh->hh_lock); 1247 seqlock_init(&hh->hh_lock);
1247 hh->hh_type = protocol;
1248 atomic_set(&hh->hh_refcnt, 2); 1248 atomic_set(&hh->hh_refcnt, 2);
1249 1249
1250 if (dev->header_ops->cache(n, hh, protocol)) { 1250 if (dev->header_ops->cache(n, hh, protocol)) {
@@ -1255,7 +1255,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1255 write_lock_bh(&n->lock); 1255 write_lock_bh(&n->lock);
1256 1256
1257 /* must check if another thread already did the insert */ 1257 /* must check if another thread already did the insert */
1258 if (neigh_hh_lookup(n, dst, protocol)) { 1258 if (neigh_hh_lookup(n, dst)) {
1259 kfree(hh); 1259 kfree(hh);
1260 goto end; 1260 goto end;
1261 } 1261 }
@@ -1265,7 +1265,6 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
1265 else 1265 else
1266 hh->hh_output = n->ops->output; 1266 hh->hh_output = n->ops->output;
1267 1267
1268 hh->hh_next = n->hh;
1269 smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */ 1268 smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */
1270 n->hh = hh; 1269 n->hh = hh;
1271 1270