⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 neighbour.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	return *pos ? NULL : n;}static struct pneigh_entry *pneigh_get_first(struct seq_file *seq){	struct neigh_seq_state *state = seq->private;	struct neigh_table *tbl = state->tbl;	struct pneigh_entry *pn = NULL;	int bucket = state->bucket;	state->flags |= NEIGH_SEQ_IS_PNEIGH;	for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {		pn = tbl->phash_buckets[bucket];		if (pn)			break;	}	state->bucket = bucket;	return pn;}static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,					    struct pneigh_entry *pn,					    loff_t *pos){	struct neigh_seq_state *state = seq->private;	struct neigh_table *tbl = state->tbl;	pn = pn->next;	while (!pn) {		if (++state->bucket > PNEIGH_HASHMASK)			break;		pn = tbl->phash_buckets[state->bucket];		if (pn)			break;	}	if (pn && pos)		--(*pos);	return pn;}static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos){	struct pneigh_entry *pn = pneigh_get_first(seq);	if (pn) {		while (*pos) {			pn = pneigh_get_next(seq, pn, pos);			if (!pn)				break;		}	}	return *pos ? NULL : pn;}static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos){	struct neigh_seq_state *state = seq->private;	void *rc;	rc = neigh_get_idx(seq, pos);	if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))		rc = pneigh_get_idx(seq, pos);	return rc;}void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags){	struct neigh_seq_state *state = seq->private;	loff_t pos_minus_one;	state->tbl = tbl;	state->bucket = 0;	state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);	read_lock_bh(&tbl->lock);	pos_minus_one = *pos - 1;	return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;}EXPORT_SYMBOL(neigh_seq_start);void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct neigh_seq_state *state;	void *rc;	if (v == SEQ_START_TOKEN) {		rc = neigh_get_idx(seq, pos);		goto out;	}	state = seq->private;	if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {		rc = neigh_get_next(seq, v, NULL);		if (rc)			goto out;		if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))			rc = pneigh_get_first(seq);	} else {		BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);		rc = pneigh_get_next(seq, v, NULL);	}out:	++(*pos);	return rc;}EXPORT_SYMBOL(neigh_seq_next);void neigh_seq_stop(struct seq_file *seq, void *v){	struct neigh_seq_state *state = seq->private;	struct neigh_table *tbl = state->tbl;	read_unlock_bh(&tbl->lock);}EXPORT_SYMBOL(neigh_seq_stop);/* statistics via seq_file */static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos){	struct proc_dir_entry *pde = seq->private;	struct neigh_table *tbl = pde->data;	int cpu;	if (*pos == 0)		return SEQ_START_TOKEN;	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {		if (!cpu_possible(cpu))			continue;		*pos = cpu+1;		return per_cpu_ptr(tbl->stats, cpu);	}	return NULL;}static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct proc_dir_entry *pde = seq->private;	struct neigh_table *tbl = pde->data;	int cpu;	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {		if (!cpu_possible(cpu))			continue;		*pos = cpu+1;		return per_cpu_ptr(tbl->stats, cpu);	}	return NULL;}static void neigh_stat_seq_stop(struct seq_file *seq, void *v){}static int neigh_stat_seq_show(struct seq_file *seq, void *v){	struct proc_dir_entry *pde = seq->private;	struct neigh_table *tbl = pde->data;	struct neigh_statistics *st = v;	if (v == SEQ_START_TOKEN) {		seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs\n");		return 0;	}	seq_printf(seq, "%08x  %08lx %08lx %08lx  %08lx %08lx  %08lx  "			"%08lx %08lx  %08lx %08lx\n",		   atomic_read(&tbl->entries),		   st->allocs,		   st->destroys,		   st->hash_grows,		   st->lookups,		   st->hits,		   st->res_failed,		   st->rcv_probes_mcast,		   st->rcv_probes_ucast,		   st->periodic_gc_runs,		   st->forced_gc_runs		   );	return 0;}static const struct seq_operations neigh_stat_seq_ops = {	.start	= neigh_stat_seq_start,	.next	= neigh_stat_seq_next,	.stop	= neigh_stat_seq_stop,	.show	= neigh_stat_seq_show,};static int neigh_stat_seq_open(struct inode *inode, struct file *file){	int ret = seq_open(file, &neigh_stat_seq_ops);	if (!ret) {		struct seq_file *sf = file->private_data;		sf->private = PDE(inode);	}	return ret;};static const struct file_operations neigh_stat_seq_fops = {	.owner	 = THIS_MODULE,	.open 	 = neigh_stat_seq_open,	.read	 = seq_read,	.llseek	 = seq_lseek,	.release = seq_release,};#endif /* CONFIG_PROC_FS */static inline size_t neigh_nlmsg_size(void){	return NLMSG_ALIGN(sizeof(struct ndmsg))	       + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */	       + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */	       + nla_total_size(sizeof(struct nda_cacheinfo))	       + nla_total_size(4); /* NDA_PROBES */}static void __neigh_notify(struct neighbour *n, int type, int flags){	struct sk_buff *skb;	int err = -ENOBUFS;	skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);	if (skb == NULL)		goto errout;	err = neigh_fill_info(skb, n, 0, 0, type, flags);	if (err < 0) {		/* -EMSGSIZE implies BUG in neigh_nlmsg_size() */		WARN_ON(err == -EMSGSIZE);		kfree_skb(skb);		goto errout;	}	err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);errout:	if (err < 0)		rtnl_set_sk_err(RTNLGRP_NEIGH, err);}#ifdef CONFIG_ARPDvoid neigh_app_ns(struct neighbour *n){	__neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);}#endif /* CONFIG_ARPD */#ifdef CONFIG_SYSCTLstatic struct neigh_sysctl_table {	struct ctl_table_header *sysctl_header;	ctl_table		neigh_vars[__NET_NEIGH_MAX];	ctl_table		neigh_dev[2];	ctl_table		neigh_neigh_dir[2];	ctl_table		neigh_proto_dir[2];	ctl_table		neigh_root_dir[2];} neigh_sysctl_template __read_mostly = {	.neigh_vars = {		{			.ctl_name	= NET_NEIGH_MCAST_SOLICIT,			.procname	= "mcast_solicit",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_NEIGH_UCAST_SOLICIT,			.procname	= "ucast_solicit",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_NEIGH_APP_SOLICIT,			.procname	= "app_solicit",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.procname	= "retrans_time",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_userhz_jiffies,		},		{			.ctl_name	= NET_NEIGH_REACHABLE_TIME,			.procname	= "base_reachable_time",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_jiffies,			.strategy	= &sysctl_jiffies,		},		{			.ctl_name	= NET_NEIGH_DELAY_PROBE_TIME,			.procname	= "delay_first_probe_time",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_jiffies,			.strategy	= &sysctl_jiffies,		},		{			.ctl_name	= NET_NEIGH_GC_STALE_TIME,			.procname	= "gc_stale_time",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_jiffies,			.strategy	= &sysctl_jiffies,		},		{			.ctl_name	= NET_NEIGH_UNRES_QLEN,			.procname	= "unres_qlen",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_NEIGH_PROXY_QLEN,			.procname	= "proxy_qlen",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.procname	= "anycast_delay",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_userhz_jiffies,		},		{			.procname	= "proxy_delay",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_userhz_jiffies,		},		{			.procname	= "locktime",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_userhz_jiffies,		},		{			.ctl_name	= NET_NEIGH_RETRANS_TIME_MS,			.procname	= "retrans_time_ms",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_ms_jiffies,			.strategy	= &sysctl_ms_jiffies,		},		{			.ctl_name	= NET_NEIGH_REACHABLE_TIME_MS,			.procname	= "base_reachable_time_ms",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_ms_jiffies,			.strategy	= &sysctl_ms_jiffies,		},		{			.ctl_name	= NET_NEIGH_GC_INTERVAL,			.procname	= "gc_interval",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec_jiffies,			.strategy	= &sysctl_jiffies,		},		{			.ctl_name	= NET_NEIGH_GC_THRESH1,			.procname	= "gc_thresh1",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_NEIGH_GC_THRESH2,			.procname	= "gc_thresh2",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_NEIGH_GC_THRESH3,			.procname	= "gc_thresh3",			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{}	},	.neigh_dev = {		{			.ctl_name	= NET_PROTO_CONF_DEFAULT,			.procname	= "default",			.mode		= 0555,		},	},	.neigh_neigh_dir = {		{			.procname	= "neigh",			.mode		= 0555,		},	},	.neigh_proto_dir = {		{			.mode		= 0555,		},	},	.neigh_root_dir = {		{			.ctl_name	= CTL_NET,			.procname	= "net",			.mode		= 0555,		},	},};int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,			  int p_id, int pdev_id, char *p_name,			  proc_handler *handler, ctl_handler *strategy){	struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template,					       sizeof(*t), GFP_KERNEL);	const char *dev_name_source = NULL;	char *dev_name = NULL;	int err = 0;	if (!t)		return -ENOBUFS;	t->neigh_vars[0].data  = &p->mcast_probes;	t->neigh_vars[1].data  = &p->ucast_probes;	t->neigh_vars[2].data  = &p->app_probes;	t->neigh_vars[3].data  = &p->retrans_time;	t->neigh_vars[4].data  = &p->base_reachable_time;	t->neigh_vars[5].data  = &p->delay_probe_time;	t->neigh_vars[6].data  = &p->gc_staletime;	t->neigh_vars[7].data  = &p->queue_len;	t->neigh_vars[8].data  = &p->proxy_qlen;	t->neigh_vars[9].data  = &p->anycast_delay;	t->neigh_vars[10].data = &p->proxy_delay;	t->neigh_vars[11].data = &p->locktime;	t->neigh_vars[12].data  = &p->retrans_time;	t->neigh_vars[13].data  = &p->base_reachable_time;	if (dev) {		dev_name_source = dev->name;		t->neigh_dev[0].ctl_name = dev->ifindex;		/* Terminate the table early */		memset(&t->neigh_vars[14], 0, sizeof(t->neigh_vars[14]));	} else {		dev_name_source = t->neigh_dev[0].procname;		t->neigh_vars[14].data = (int *)(p + 1);		t->neigh_vars[15].data = (int *)(p + 1) + 1;		t->neigh_vars[16].data = (int *)(p + 1) + 2;		t->neigh_vars[17].data = (int *)(p + 1) + 3;	}	if (handler || strategy) {		/* RetransTime */		t->neigh_vars[3].proc_handler = handler;		t->neigh_vars[3].strategy = strategy;		t->neigh_vars[3].extra1 = dev;		if (!strategy)			t->neigh_vars[3].ctl_name = CTL_UNNUMBERED;		/* ReachableTime */		t->neigh_vars[4].proc_handler = handler;		t->neigh_vars[4].strategy = strategy;		t->neigh_vars[4].extra1 = dev;		if (!strategy)			t->neigh_vars[4].ctl_name = CTL_UNNUMBERED;		/* RetransTime (in milliseconds)*/		t->neigh_vars[12].proc_handler = handler;		t->neigh_vars[12].strategy = strategy;		t->neigh_vars[12].extra1 = dev;		if (!strategy)			t->neigh_vars[12].ctl_name = CTL_UNNUMBERED;		/* ReachableTime (in milliseconds) */		t->neigh_vars[13].proc_handler = handler;		t->neigh_vars[13].strategy = strategy;		t->neigh_vars[13].extra1 = dev;		if (!strategy)			t->neigh_vars[13].ctl_name = CTL_UNNUMBERED;	}	dev_name = kstrdup(dev_name_source, GFP_KERNEL);	if (!dev_name) {		err = -ENOBUFS;		goto free;	}	t->neigh_dev[0].procname = dev_name;	t->neigh_neigh_dir[0].ctl_name = pdev_id;	t->neigh_proto_dir[0].procname = p_name;	t->neigh_proto_dir[0].ctl_name = p_id;	t->neigh_dev[0].child	       = t->neigh_vars;	t->neigh_neigh_dir[0].child    = t->neigh_dev;	t->neigh_proto_dir[0].child    = t->neigh_neigh_dir;	t->neigh_root_dir[0].child     = t->neigh_proto_dir;	t->sysctl_header = register_sysctl_table(t->neigh_root_dir);	if (!t->sysctl_header) {		err = -ENOBUFS;		goto free_procname;	}	p->sysctl_table = t;	return 0;	/* error path */ free_procname:	kfree(dev_name); free:	kfree(t);	return err;}void neigh_sysctl_unregister(struct neigh_parms *p){	if (p->sysctl_table) {		struct neigh_sysctl_table *t = p->sysctl_table;		p->sysctl_table = NULL;		unregister_sysctl_table(t->sysctl_header);		kfree(t->neigh_dev[0].procname);		kfree(t);	}}#endif	/* CONFIG_SYSCTL */static int __init neigh_init(void){	rtnl_register(PF_U

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -