* Harald Welte Add neighbour cache statistics like rtstat
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/sock.h>
-#include <net/netevent.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>
struct neighbour **ret;
if (size <= PAGE_SIZE) {
- ret = kzalloc(size, GFP_ATOMIC);
+ ret = kmalloc(size, GFP_ATOMIC);
} else {
ret = (struct neighbour **)
- __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
+ __get_free_pages(GFP_ATOMIC, get_order(size));
}
+ if (ret)
+ memset(ret, 0, size);
+
return ret;
}
kfree(hh);
}
- if (neigh->parms->neigh_destructor)
- (neigh->parms->neigh_destructor)(neigh);
+ if (neigh->ops && neigh->ops->destructor)
+ (neigh->ops->destructor)(neigh);
skb_queue_purge(&neigh->arp_queue);
neigh->used + neigh->parms->delay_probe_time)) {
NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
neigh->nud_state = NUD_DELAY;
- neigh->updated = jiffies;
neigh_suspect(neigh);
next = now + neigh->parms->delay_probe_time;
} else {
NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
neigh->nud_state = NUD_STALE;
- neigh->updated = jiffies;
neigh_suspect(neigh);
- notify = 1;
}
} else if (state & NUD_DELAY) {
if (time_before_eq(now,
neigh->confirmed + neigh->parms->delay_probe_time)) {
NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
neigh->nud_state = NUD_REACHABLE;
- neigh->updated = jiffies;
neigh_connect(neigh);
- notify = 1;
next = neigh->confirmed + neigh->parms->reachable_time;
} else {
NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
neigh->nud_state = NUD_PROBE;
- neigh->updated = jiffies;
atomic_set(&neigh->probes, 0);
next = now + neigh->parms->retrans_time;
}
struct sk_buff *skb;
neigh->nud_state = NUD_FAILED;
- neigh->updated = jiffies;
notify = 1;
NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
out:
write_unlock(&neigh->lock);
}
- if (notify)
- call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
#ifdef CONFIG_ARPD
if (notify && neigh->parms->app_probes)
if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
atomic_set(&neigh->probes, neigh->parms->ucast_probes);
neigh->nud_state = NUD_INCOMPLETE;
- neigh->updated = jiffies;
neigh_hold(neigh);
neigh_add_timer(neigh, now + 1);
} else {
neigh->nud_state = NUD_FAILED;
- neigh->updated = jiffies;
write_unlock_bh(&neigh->lock);
if (skb)
NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
neigh_hold(neigh);
neigh->nud_state = NUD_DELAY;
- neigh->updated = jiffies;
neigh_add_timer(neigh,
jiffies + neigh->parms->delay_probe_time);
}
{
u8 old;
int err;
+#ifdef CONFIG_ARPD
int notify = 0;
+#endif
struct net_device *dev;
int update_isrouter = 0;
neigh_suspect(neigh);
neigh->nud_state = new;
err = 0;
+#ifdef CONFIG_ARPD
notify = old & NUD_VALID;
+#endif
goto out;
}
if (!(new & NUD_CONNECTED))
neigh->confirmed = jiffies -
(neigh->parms->base_reachable_time << 1);
+#ifdef CONFIG_ARPD
notify = 1;
+#endif
}
if (new == old)
goto out;
(neigh->flags & ~NTF_ROUTER);
}
write_unlock_bh(&neigh->lock);
-
- if (notify)
- call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
#ifdef CONFIG_ARPD
if (notify && neigh->parms->app_probes)
neigh_app_notify(neigh);
if (hh->hh_type == protocol)
break;
- if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
+ if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
+ memset(hh, 0, sizeof(struct hh_cache));
rwlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
kfree(parms);
}
-void neigh_table_init_no_netlink(struct neigh_table *tbl)
+
+void neigh_table_init(struct neigh_table *tbl)
{
unsigned long now = jiffies;
unsigned long phsize;
tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
- tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
+ tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
if (!tbl->hash_buckets || !tbl->phash_buckets)
panic("cannot allocate neighbour cache hashes");
+ memset(tbl->phash_buckets, 0, phsize);
+
get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
rwlock_init(&tbl->lock);
tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20;
-}
-
-void neigh_table_init(struct neigh_table *tbl)
-{
- struct neigh_table *tmp;
-
- neigh_table_init_no_netlink(tbl);
write_lock(&neigh_tbl_lock);
- for (tmp = neigh_tables; tmp; tmp = tmp->next) {
- if (tmp->family == tbl->family)
- break;
- }
tbl->next = neigh_tables;
neigh_tables = tbl;
write_unlock(&neigh_tbl_lock);
-
- if (unlikely(tmp)) {
- printk(KERN_ERR "NEIGH: Registering multiple tables for "
- "family %d\n", tbl->family);
- dump_stack();
- }
}
int neigh_table_clear(struct neigh_table *tbl)
kfree(tbl->phash_buckets);
tbl->phash_buckets = NULL;
- free_percpu(tbl->stats);
- tbl->stats = NULL;
-
return 0;
}
memset(&ndst, 0, sizeof(ndst));
- for_each_possible_cpu(cpu) {
+ for_each_cpu(cpu) {
struct neigh_statistics *st;
st = per_cpu_ptr(tbl->stats, cpu);
EXPORT_SYMBOL(neigh_resolve_output);
EXPORT_SYMBOL(neigh_table_clear);
EXPORT_SYMBOL(neigh_table_init);
-EXPORT_SYMBOL(neigh_table_init_no_netlink);
EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);