: Abstract neigh table walking
Subsystems (4)
David S. Miller
maintainerPATCH 1/6 : Abstract neigh table walking
This way we can hide hash table accesses inside
of net/core/neigh.c
# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/09/23 15:15:26-07:00 [email protected]
# [NET]: Abstract neigh table walking.
#
# This way no code actually needs to traverse the
# neigh hash tables outside of net/core/neighbour.c
#
# Signed-off-by: David S. Miller <[email protected]>
#
# net/ipv4/arp.c # 2004/09/23 15:14:50-07:00 [email protected] +20 -163 # [NET]: Abstract neigh table walking. # # This way no code actually needs to traverse the # neigh hash tables outside of net/core/neighbour.c # # Signed-off-by: David S. Miller <[email protected]> # # net/decnet/dn_neigh.c # 2004/09/23 15:14:50-07:00 [email protected] +52 -120 # [NET]: Abstract neigh table walking. # # This way no code actually needs to traverse the # neigh hash tables outside of net/core/neighbour.c # # Signed-off-by: David S. Miller <[email protected]> # # net/core/neighbour.c # 2004/09/23 15:14:50-07:00 [email protected] +260 -0 # [NET]: Abstract neigh table walking. # # This way no code actually needs to traverse the # neigh hash tables outside of net/core/neighbour.c # # Signed-off-by: David S. Miller <[email protected]> # # net/atm/clip.c # 2004/09/23 15:14:50-07:00 [email protected] +117 -129 # [NET]: Abstract neigh table walking. # # This way no code actually needs to traverse the # neigh hash tables outside of net/core/neighbour.c # # Signed-off-by: David S. Miller <[email protected]> # # include/net/neighbour.h # 2004/09/23 15:14:49-07:00 [email protected] +19 -0 # [NET]: Abstract neigh table walking. # # This way no code actually needs to traverse the # neigh hash tables outside of net/core/neighbour.c # # Signed-off-by: David S. Miller <[email protected]> # diff -Nru a/include/net/neighbour.h b/include/net/neighbour.h --- a/include/net/neighbour.h 2004-09-23 22:25:53 -07:00 +++ b/include/net/neighbour.h 2004-09-23 22:25:53 -07:00 @@ -47,6 +47,7 @@ #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/rcupdate.h> +#include <linux/seq_file.h>
#include <linux/err.h>
#include <linux/sysctl.h>
@@ -223,6 +224,24 @@
extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern void neigh_app_ns(struct neighbour *n);
+
+extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); +extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *)); +extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); +
+struct neigh_seq_state {
+ struct neigh_table *tbl;
+ void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+ struct neighbour *n, loff_t *pos);
+ unsigned int bucket;
+ unsigned int flags;
+#define NEIGH_SEQ_NEIGH_ONLY 0x00000001
+#define NEIGH_SEQ_IS_PNEIGH 0x00000002
+#define NEIGH_SEQ_SKIP_NOARP 0x00000004
+};
+extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int); +extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+extern void neigh_seq_stop(struct seq_file *, void *);
extern int neigh_sysctl_register(struct net_device *dev,
struct neigh_parms *p,
net/atm/clip.c +117 -129
@@ -123,64 +123,49 @@spin_unlock_bh (&entry->neigh->dev->xmit_lock); } - -static void idle_timer_check (unsigned long dummy) +/* The neighbour entry n->lock is held. */ +static int neigh_check_cb (struct neighbour *n) { -int i; +struct atmarp_entry *entry =NEIGH2ENTRY (n); +struct clip_vcc *cv; -/*DPRINTK("idle_timer_check\n");*/ -write_lock (&clip_tbl.lock); -for (i =0 ; i <=NEIGH_HASHMASK ; i++) { -struct neighbour **np; +for (cv = entry->vccs; cv; cv = cv->next) { +unsigned long exp = cv->last_use + cv->idle_timeout; -for (np = &clip_tbl.hash_buckets[i]; *np;) { -struct neighbour *n = *np; -struct atmarp_entry *entry =NEIGH2ENTRY (n); -struct clip_vcc *clip_vcc; - -write_lock (&n->lock); - -for (clip_vcc = entry->vccs; clip_vcc; - clip_vcc = clip_vcc->next) -if (clip_vcc->idle_timeout && -time_after (jiffies, clip_vcc->last_use+ - clip_vcc->idle_timeout)) { -DPRINTK ("releasing vcc %p->%p of " -"entry %p\n" ,clip_vcc,clip_vcc->vcc, - entry); -vcc_release_async (clip_vcc->vcc, - -ETIMEDOUT ); - } -if (entry->vccs || -time_before (jiffies, entry->expires)) { - np = &n->next; -write_unlock (&n->lock); -continue ; - } -if (atomic_read (&n->refcnt) >1 ) { -struct sk_buff *skb; - -DPRINTK ("destruction postponed with ref %d\n" , -atomic_read (&n->refcnt)); -while ((skb =skb_dequeue (&n->arp_queue)) != -NULL ) -dev_kfree_skb (skb); - np = &n->next; -write_unlock (&n->lock); -continue ; - } - *np = n->next; -DPRINTK ("expired neigh %p\n" ,n); - n->dead =1 ; -write_unlock (&n->lock); -neigh_release (n); +if (cv->idle_timeout &&time_after (jiffies, exp)) { +DPRINTK ("releasing vcc %p->%p of entry %p\n" , + cv, cv->vcc, entry); +vcc_release_async (cv->vcc, -ETIMEDOUT ); } } + +if (entry->vccs ||time_before (jiffies, entry->expires)) +return 0 ; + +if (atomic_read (&n->refcnt) >1 ) { +struct sk_buff *skb; + +DPRINTK ("destruction postponed with ref %d\n" , +atomic_read (&n->refcnt)); + +while ((skb =skb_dequeue (&n->arp_queue)) !=NULL ) +dev_kfree_skb (skb); + +return 0 ; + } + +DPRINTK ("expired neigh %p\n" ,n); +return 1 ; +} + +static void idle_timer_check (unsigned long dummy) +{ +write_lock (&clip_tbl.lock); +__neigh_for_each_release (&clip_tbl, neigh_check_cb);mod_timer (&idle_timer, jiffies+CLIP_CHECK_INTERVAL *HZ );write_unlock (&clip_tbl.lock); } -static int clip_arp_rcv (struct sk_buff *skb) {struct atm_vcc *vcc;
@@ -833,120 +818,126 @@ } } +/* This means the neighbour entry has no attached VCC objects. */ +#define SEQ_NO_VCC_TOKEN ((void *) 2) +static void atmarp_info (struct seq_file *seq,struct net_device *dev,struct atmarp_entry *entry,struct clip_vcc *clip_vcc) { +unsigned long exp;char buf[17 ]; -int svc, off; +int svc, llc, off; + + svc = ((clip_vcc ==SEQ_NO_VCC_TOKEN ) || + (clip_vcc->vcc->sk->sk_family ==AF_ATMSVC )); + + llc = ((clip_vcc ==SEQ_NO_VCC_TOKEN ) || + clip_vcc->encap); + +if (clip_vcc ==SEQ_NO_VCC_TOKEN ) + exp = entry->neigh->used; +else + exp = clip_vcc->last_use; - svc = !clip_vcc || clip_vcc->vcc->sk->sk_family ==AF_ATMSVC ; -seq_printf (seq,"%-6s%-4s%-4s%5ld " , dev->name, svc ?"SVC" :"PVC" , - !clip_vcc || clip_vcc->encap ?"LLC" :"NULL" , - (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ ); + exp = (jiffies - exp) /HZ ; - off =scnprintf (buf,sizeof (buf) -1 ,"%d.%d.%d.%d" ,NIPQUAD (entry->ip)); +seq_printf (seq,"%-6s%-4s%-4s%5ld " , + dev->name, + svc ?"SVC" :"PVC" , + llc ?"LLC" :"NULL" , + exp); + + off =scnprintf (buf,sizeof (buf) -1 ,"%d.%d.%d.%d" , +NIPQUAD (entry->ip));while (off <16 ) buf[off++] =' ' ; buf[off] ='\0' ;seq_printf (seq,"%s" , buf); -if (!clip_vcc) { +if (clip_vcc ==SEQ_NO_VCC_TOKEN ) {if (time_before (jiffies, entry->expires))seq_printf (seq,"(resolving)\n" );else seq_printf (seq,"(expired, ref %d)\n" ,atomic_read (&entry->neigh->refcnt)); }else if (!svc) { -seq_printf (seq,"%d.%d.%d\n" , clip_vcc->vcc->dev->number, - clip_vcc->vcc->vpi, clip_vcc->vcc->vci); +seq_printf (seq,"%d.%d.%d\n" , + clip_vcc->vcc->dev->number, + clip_vcc->vcc->vpi, + clip_vcc->vcc->vci); }else {svc_addr (seq, &clip_vcc->vcc->remote);seq_putc (seq,'\n' ); } } -struct arp_state { -int bucket; -struct neighbour *n; +struct clip_seq_state { +/* This member must be first. */ +struct neigh_seq_state ns; + +/* Local to clip specific iteration. */ struct clip_vcc *vcc; }; - -static void *arp_vcc_walk (struct arp_state *state, -struct atmarp_entry *e,loff_t *l) -{ -struct clip_vcc *vcc = state->vcc; -if (!vcc) - vcc = e->vccs; -if (vcc == (void *)1 ) { - vcc = e->vccs; - --*l; - } -for (; vcc; vcc = vcc->next) { -if (--*l <0 ) -break ; - } - state->vcc = vcc; -return (*l <0 ) ? state :NULL ; -} - -static void *arp_get_idx (struct arp_state *state,loff_t l) +static struct clip_vcc *clip_seq_next_vcc (struct atmarp_entry *e, +struct clip_vcc *curr) { -void *v =NULL ; - -for (; state->bucket <=NEIGH_HASHMASK ; state->bucket++) { -for (; state->n; state->n = state->n->next) { - v =arp_vcc_walk (state,NEIGH2ENTRY (state->n), &l); -if (v) - goto done; - } - state->n = clip_tbl.hash_buckets[state->bucket +1 ]; +if (!curr) { + curr = e->vccs; +if (!curr) +return SEQ_NO_VCC_TOKEN ; +return curr; } -done: -return v; +if (curr ==SEQ_NO_VCC_TOKEN ) +return NULL ; + + curr = curr->next; + +return curr; } -static void *arp_seq_start (struct seq_file *seq,loff_t *pos) +static void *clip_seq_vcc_walk (struct clip_seq_state *state, +struct atmarp_entry *e,loff_t *pos) { -struct arp_state *state = seq->private; -void *ret = (void *)1 ; +struct clip_vcc *vcc = state->vcc; -read_lock_bh (&clip_tbl.lock); - state->bucket =0 ; - state->n = clip_tbl.hash_buckets[0 ]; - state->vcc = (void *)1 ; -if (*pos) - ret =arp_get_idx (state, *pos); -return ret; -} + vcc =clip_seq_next_vcc (e, vcc); +if (vcc && pos !=NULL ) { +while (*pos) { + vcc =clip_seq_next_vcc (e, vcc); +if (!vcc) +break ; + --(*pos); + } + } + state->vcc = vcc; -static void arp_seq_stop (struct seq_file *seq,void *v) +return vcc; +} + +static void *clip_seq_sub_iter (struct neigh_seq_state *_state, +struct neighbour *n,loff_t *pos) { -struct arp_state *state = seq->private; +struct clip_seq_state *state = (struct clip_seq_state *) _state; -if (state->bucket !=-1 ) -read_unlock_bh (&clip_tbl.lock); +return clip_seq_vcc_walk (state,NEIGH2ENTRY (n), pos); } -static void *arp_seq_next (struct seq_file *seq,void *v,loff_t *pos) +static void *clip_seq_start (struct seq_file *seq,loff_t *pos) { -struct arp_state *state = seq->private; - - v =arp_get_idx (state,1 ); - *pos += !!PTR_ERR (v); -return v; +return neigh_seq_start (seq, pos, &clip_tbl,NEIGH_SEQ_NEIGH_ONLY ); } -static int arp_seq_show (struct seq_file *seq,void *v) +static int clip_seq_show (struct seq_file *seq,void *v) {static char atm_arp_banner[] ="IPitf TypeEncp Idle IP address ATM address\n" ; -if (v == (void *)1 ) +if (v ==SEQ_START_TOKEN ) {seq_puts (seq, atm_arp_banner); -else { -struct arp_state *state = seq->private; -struct neighbour *n = state->n; + }else { +struct clip_seq_state *state = seq->private; +struct neighbour *n = v;struct clip_vcc *vcc = state->vcc;atmarp_info (seq, n->dev,NEIGH2ENTRY (n), vcc);
@@ -955,15 +946,15 @@ }static struct seq_operations arp_seq_ops = { - .start = arp_seq_start, - .next = arp_seq_next, - .stop = arp_seq_stop, - .show = arp_seq_show, + .start = clip_seq_start, + .next = neigh_seq_next, + .stop = neigh_seq_stop, + .show = clip_seq_show, };static int arp_seq_open (struct inode *inode,struct file *file) { -struct arp_state *state; +struct clip_seq_state *state;struct seq_file *seq;int rc = -EAGAIN ;
@@ -972,6 +963,8 @@ rc = -ENOMEM ; goto out_kfree; } +memset (state,0 ,sizeof (*state)); + state->ns.neigh_sub_iter = clip_seq_sub_iter; rc =seq_open (file, &arp_seq_ops);if (rc)
@@ -987,16 +980,11 @@ goto out; } -static int arp_seq_release (struct inode *inode,struct file *file) -{ -return seq_release_private (inode, file); -} -static struct file_operations arp_seq_fops = { .open = arp_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = arp_seq_release, + .release = seq_release_private, .owner =THIS_MODULE };#endif
net/core/neighbour.c +260 -0
266 lines not on this page · raw message
net/decnet/dn_neigh.c +52 -120
214 lines not on this page · raw message
net/ipv4/arp.c +20 -163
226 lines not on this page · raw message