neighbour.c (5c25f686db352082eef8daa21b760192351a023a) | neighbour.c (f6b72b6217f8c24f2a54988e58af858b4e66024d) |
---|---|
1/* 2 * Generic address resolution entity 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * 8 * This program is free software; you can redistribute it and/or --- 283 unchanged lines hidden (view full) --- 292 goto out_entries; 293 294 skb_queue_head_init(&n->arp_queue); 295 rwlock_init(&n->lock); 296 seqlock_init(&n->ha_lock); 297 n->updated = n->used = now; 298 n->nud_state = NUD_NONE; 299 n->output = neigh_blackhole; | 1/* 2 * Generic address resolution entity 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * 8 * This program is free software; you can redistribute it and/or --- 283 unchanged lines hidden (view full) --- 292 goto out_entries; 293 294 skb_queue_head_init(&n->arp_queue); 295 rwlock_init(&n->lock); 296 seqlock_init(&n->ha_lock); 297 n->updated = n->used = now; 298 n->nud_state = NUD_NONE; 299 n->output = neigh_blackhole; |
300 seqlock_init(&n->hh.hh_lock); |
|
300 n->parms = neigh_parms_clone(&tbl->parms); 301 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); 302 303 NEIGH_CACHE_STAT_INC(tbl, allocs); 304 n->tbl = tbl; 305 atomic_set(&n->refcnt, 1); 306 n->dead = 1; 307out: --- 389 unchanged lines hidden (view full) --- 697 "Destroying alive neighbour %p\n", neigh); 698 dump_stack(); 699 return; 700 } 701 702 if (neigh_del_timer(neigh)) 703 printk(KERN_WARNING "Impossible event.\n"); 704 | 301 n->parms = neigh_parms_clone(&tbl->parms); 302 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n); 303 304 NEIGH_CACHE_STAT_INC(tbl, allocs); 305 n->tbl = tbl; 306 atomic_set(&n->refcnt, 1); 307 n->dead = 1; 308out: --- 389 unchanged lines hidden (view full) --- 698 "Destroying alive neighbour %p\n", neigh); 699 dump_stack(); 700 return; 701 } 702 703 if (neigh_del_timer(neigh)) 704 printk(KERN_WARNING "Impossible event.\n"); 705 |
705 hh = neigh->hh; 706 if (hh) { 707 neigh->hh = NULL; 708 | 706 hh = &neigh->hh; 707 if (hh->hh_len) { |
709 write_seqlock_bh(&hh->hh_lock); 710 hh->hh_output = neigh_blackhole; 711 write_sequnlock_bh(&hh->hh_lock); | 708 write_seqlock_bh(&hh->hh_lock); 709 hh->hh_output = neigh_blackhole; 710 write_sequnlock_bh(&hh->hh_lock); |
712 hh_cache_put(hh); | |
713 } 714 715 skb_queue_purge(&neigh->arp_queue); 716 717 dev_put(neigh->dev); 718 neigh_parms_put(neigh->parms); 719 720 NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh); --- 11 unchanged lines hidden (view full) --- 732static void neigh_suspect(struct neighbour *neigh) 733{ 734 struct hh_cache *hh; 735 736 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); 737 738 neigh->output = neigh->ops->output; 739 | 711 } 712 713 skb_queue_purge(&neigh->arp_queue); 714 715 dev_put(neigh->dev); 716 neigh_parms_put(neigh->parms); 717 718 NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh); --- 11 unchanged lines hidden (view full) --- 730static void neigh_suspect(struct neighbour *neigh) 731{ 732 struct hh_cache *hh; 733 734 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); 735 736 neigh->output = neigh->ops->output; 737 |
740 hh = neigh->hh; 741 if (hh) | 738 hh = &neigh->hh; 739 if (hh->hh_len) |
742 hh->hh_output = neigh->ops->output; 743} 744 745/* Neighbour state is OK; 746 enable fast path. 747 748 Called with write_locked neigh. 749 */ 750static void neigh_connect(struct neighbour *neigh) 751{ 752 struct hh_cache *hh; 753 754 NEIGH_PRINTK2("neigh %p is connected.\n", neigh); 755 756 neigh->output = neigh->ops->connected_output; 757 | 740 hh->hh_output = neigh->ops->output; 741} 742 743/* Neighbour state is OK; 744 enable fast path. 745 746 Called with write_locked neigh. 747 */ 748static void neigh_connect(struct neighbour *neigh) 749{ 750 struct hh_cache *hh; 751 752 NEIGH_PRINTK2("neigh %p is connected.\n", neigh); 753 754 neigh->output = neigh->ops->connected_output; 755 |
758 hh = neigh->hh; 759 if (hh) | 756 hh = &neigh->hh; 757 if (hh->hh_len) |
760 hh->hh_output = neigh->ops->hh_output; 761} 762 763static void neigh_periodic_work(struct work_struct *work) 764{ 765 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work); 766 struct neighbour *n; 767 struct neighbour __rcu **np; --- 244 unchanged lines hidden (view full) --- 1012 rc = 1; 1013 } 1014out_unlock_bh: 1015 write_unlock_bh(&neigh->lock); 1016 return rc; 1017} 1018EXPORT_SYMBOL(__neigh_event_send); 1019 | 758 hh->hh_output = neigh->ops->hh_output; 759} 760 761static void neigh_periodic_work(struct work_struct *work) 762{ 763 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work); 764 struct neighbour *n; 765 struct neighbour __rcu **np; --- 244 unchanged lines hidden (view full) --- 1010 rc = 1; 1011 } 1012out_unlock_bh: 1013 write_unlock_bh(&neigh->lock); 1014 return rc; 1015} 1016EXPORT_SYMBOL(__neigh_event_send); 1017 |
1020static void neigh_update_hhs(const struct neighbour *neigh) | 1018static void neigh_update_hhs(struct neighbour *neigh) |
1021{ 1022 struct hh_cache *hh; 1023 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) 1024 = NULL; 1025 1026 if (neigh->dev->header_ops) 1027 update = neigh->dev->header_ops->cache_update; 1028 1029 if (update) { | 1019{ 1020 struct hh_cache *hh; 1021 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) 1022 = NULL; 1023 1024 if (neigh->dev->header_ops) 1025 update = neigh->dev->header_ops->cache_update; 1026 1027 if (update) { |
1030 hh = neigh->hh; 1031 if (hh) { | 1028 hh = &neigh->hh; 1029 if (hh->hh_len) { |
1032 write_seqlock_bh(&hh->hh_lock); 1033 update(hh, neigh->dev, neigh->ha); 1034 write_sequnlock_bh(&hh->hh_lock); 1035 } 1036 } 1037} 1038 1039 --- 169 unchanged lines hidden (view full) --- 1209 lladdr || !dev->addr_len); 1210 if (neigh) 1211 neigh_update(neigh, lladdr, NUD_STALE, 1212 NEIGH_UPDATE_F_OVERRIDE); 1213 return neigh; 1214} 1215EXPORT_SYMBOL(neigh_event_ns); 1216 | 1030 write_seqlock_bh(&hh->hh_lock); 1031 update(hh, neigh->dev, neigh->ha); 1032 write_sequnlock_bh(&hh->hh_lock); 1033 } 1034 } 1035} 1036 1037 --- 169 unchanged lines hidden (view full) --- 1207 lladdr || !dev->addr_len); 1208 if (neigh) 1209 neigh_update(neigh, lladdr, NUD_STALE, 1210 NEIGH_UPDATE_F_OVERRIDE); 1211 return neigh; 1212} 1213EXPORT_SYMBOL(neigh_event_ns); 1214 |
1217static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst) 1218{ 1219 struct hh_cache *hh; 1220 1221 smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */ 1222 hh = n->hh; 1223 if (hh) { 1224 atomic_inc(&hh->hh_refcnt); 1225 if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) 1226 hh_cache_put(hh); 1227 return true; 1228 } 1229 return false; 1230} 1231 | |
1232/* called with read_lock_bh(&n->lock); */ | 1215/* called with read_lock_bh(&n->lock); */ |
1233static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, 1234 __be16 protocol) | 1216static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst) |
1235{ | 1217{ |
1236 struct hh_cache *hh; | |
1237 struct net_device *dev = dst->dev; | 1218 struct net_device *dev = dst->dev; |
1219 __be16 prot = dst->ops->protocol; 1220 struct hh_cache *hh = &n->hh; |
|
1238 | 1221 |
1239 if (likely(neigh_hh_lookup(n, dst))) 1240 return; 1241 1242 /* slow path */ 1243 hh = kzalloc(sizeof(*hh), GFP_ATOMIC); 1244 if (!hh) 1245 return; 1246 1247 seqlock_init(&hh->hh_lock); 1248 atomic_set(&hh->hh_refcnt, 2); 1249 1250 if (dev->header_ops->cache(n, hh, protocol)) { 1251 kfree(hh); 1252 return; 1253 } 1254 | |
1255 write_lock_bh(&n->lock); 1256 | 1222 write_lock_bh(&n->lock); 1223 |
1257 /* must check if another thread already did the insert */ 1258 if (neigh_hh_lookup(n, dst)) { 1259 kfree(hh); | 1224 /* Only one thread can come in here and initialize the 1225 * hh_cache entry. 1226 */ 1227 if (hh->hh_len) |
1260 goto end; | 1228 goto end; |
1261 } | |
1262 | 1229 |
1230 if (dev->header_ops->cache(n, hh, prot)) 1231 goto end; 1232 |
|
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 | 1233 if (n->nud_state & NUD_CONNECTED) 1234 hh->hh_output = n->ops->hh_output; 1235 else 1236 hh->hh_output = n->ops->output; 1237 |
1268 smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */ 1269 n->hh = hh; 1270 1271 if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL)) 1272 hh_cache_put(hh); | |
1273end: 1274 write_unlock_bh(&n->lock); 1275} 1276 1277/* This function can be used in contexts, where only old dev_queue_xmit 1278 * worked, f.e. if you want to override normal output path (eql, shaper), 1279 * but resolution is not made yet. 1280 */ --- 26 unchanged lines hidden (view full) --- 1307 1308 __skb_pull(skb, skb_network_offset(skb)); 1309 1310 if (!neigh_event_send(neigh, skb)) { 1311 int err; 1312 struct net_device *dev = neigh->dev; 1313 unsigned int seq; 1314 | 1238end: 1239 write_unlock_bh(&n->lock); 1240} 1241 1242/* This function can be used in contexts, where only old dev_queue_xmit 1243 * worked, f.e. if you want to override normal output path (eql, shaper), 1244 * but resolution is not made yet. 1245 */ --- 26 unchanged lines hidden (view full) --- 1272 1273 __skb_pull(skb, skb_network_offset(skb)); 1274 1275 if (!neigh_event_send(neigh, skb)) { 1276 int err; 1277 struct net_device *dev = neigh->dev; 1278 unsigned int seq; 1279 |
1315 if (dev->header_ops->cache && 1316 !dst->hh && 1317 !(dst->flags & DST_NOCACHE)) 1318 neigh_hh_init(neigh, dst, dst->ops->protocol); | 1280 if (dev->header_ops->cache && !neigh->hh.hh_len) 1281 neigh_hh_init(neigh, dst); |
1319 1320 do { 1321 seq = read_seqbegin(&neigh->ha_lock); 1322 err = dev_hard_header(skb, dev, ntohs(skb->protocol), 1323 neigh->ha, NULL, skb->len); 1324 } while (read_seqretry(&neigh->ha_lock, seq)); 1325 1326 if (err >= 0) --- 1597 unchanged lines hidden --- | 1282 1283 do { 1284 seq = read_seqbegin(&neigh->ha_lock); 1285 err = dev_hard_header(skb, dev, ntohs(skb->protocol), 1286 neigh->ha, NULL, skb->len); 1287 } while (read_seqretry(&neigh->ha_lock, seq)); 1288 1289 if (err >= 0) --- 1597 unchanged lines hidden --- |