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 ---