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

📄 dev.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (pt_prev) {		ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);	} else {		kfree_skb(skb);		/* Jamal, now you will not able to escape explaining		 * me how you were going to use this. :-)		 */		ret = NET_RX_DROP;	}out:	rcu_read_unlock();	return ret;}static int process_backlog(struct napi_struct *napi, int quota){	int work = 0;	struct softnet_data *queue = &__get_cpu_var(softnet_data);	unsigned long start_time = jiffies;	napi->weight = weight_p;	do {		struct sk_buff *skb;		struct net_device *dev;		local_irq_disable();		skb = __skb_dequeue(&queue->input_pkt_queue);		if (!skb) {			__napi_complete(napi);			local_irq_enable();			break;		}		local_irq_enable();		dev = skb->dev;		netif_receive_skb(skb);		dev_put(dev);	} while (++work < quota && jiffies == start_time);	return work;}/** * __napi_schedule - schedule for receive * @n: entry to schedule * * The entry's receive function will be scheduled to run */void fastcall __napi_schedule(struct napi_struct *n){	unsigned long flags;	local_irq_save(flags);	list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list);	__raise_softirq_irqoff(NET_RX_SOFTIRQ);	local_irq_restore(flags);}EXPORT_SYMBOL(__napi_schedule);static void net_rx_action(struct softirq_action *h){	struct list_head *list = &__get_cpu_var(softnet_data).poll_list;	unsigned long start_time = jiffies;	int budget = netdev_budget;	void *have;	local_irq_disable();	while (!list_empty(list)) {		struct napi_struct *n;		int work, weight;		/* If softirq window is exhuasted then punt.		 *		 * Note that this is a slight policy change from the		 * previous NAPI code, which would allow up to 2		 * jiffies to pass before breaking out.  The test		 * used to be "jiffies - start_time > 1".		 */		if (unlikely(budget <= 0 || jiffies != start_time))			goto softnet_break;		local_irq_enable();		/* Even though interrupts have been re-enabled, this		 * access is safe because interrupts can only add new		 * entries to the tail of this list, and only ->poll()		 * calls can remove this head entry from the list.		 */		n = list_entry(list->next, struct napi_struct, poll_list);		have = netpoll_poll_lock(n);		weight = n->weight;		/* This NAPI_STATE_SCHED test is for avoiding a race		 * with netpoll's poll_napi().  Only the entity which		 * obtains the lock and sees NAPI_STATE_SCHED set will		 * actually make the ->poll() call.  Therefore we avoid		 * accidently calling ->poll() when NAPI is not scheduled.		 */		work = 0;		if (test_bit(NAPI_STATE_SCHED, &n->state))			work = n->poll(n, weight);		WARN_ON_ONCE(work > weight);		budget -= work;		local_irq_disable();		/* Drivers must not modify the NAPI state if they		 * consume the entire weight.  In such cases this code		 * still "owns" the NAPI instance and therefore can		 * move the instance around on the list at-will.		 */		if (unlikely(work == weight)) {			if (unlikely(napi_disable_pending(n)))				__napi_complete(n);			else				list_move_tail(&n->poll_list, list);		}		netpoll_poll_unlock(have);	}out:	local_irq_enable();#ifdef CONFIG_NET_DMA	/*	 * There may not be any more sk_buffs coming right now, so push	 * any pending DMA copies to hardware	 */	if (!cpus_empty(net_dma.channel_mask)) {		int chan_idx;		for_each_cpu_mask(chan_idx, net_dma.channel_mask) {			struct dma_chan *chan = net_dma.channels[chan_idx];			if (chan)				dma_async_memcpy_issue_pending(chan);		}	}#endif	return;softnet_break:	__get_cpu_var(netdev_rx_stat).time_squeeze++;	__raise_softirq_irqoff(NET_RX_SOFTIRQ);	goto out;}static gifconf_func_t * gifconf_list [NPROTO];/** *	register_gifconf	-	register a SIOCGIF handler *	@family: Address family *	@gifconf: Function handler * *	Register protocol dependent address dumping routines. The handler *	that is passed must not be freed or reused until it has been replaced *	by another handler. */int register_gifconf(unsigned int family, gifconf_func_t * gifconf){	if (family >= NPROTO)		return -EINVAL;	gifconf_list[family] = gifconf;	return 0;}/* *	Map an interface index to its name (SIOCGIFNAME) *//* *	We need this ioctl for efficient implementation of the *	if_indextoname() function required by the IPv6 API.  Without *	it, we would have to search all the interfaces to find a *	match.  --pb */static int dev_ifname(struct net *net, struct ifreq __user *arg){	struct net_device *dev;	struct ifreq ifr;	/*	 *	Fetch the caller's info block.	 */	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))		return -EFAULT;	read_lock(&dev_base_lock);	dev = __dev_get_by_index(net, ifr.ifr_ifindex);	if (!dev) {		read_unlock(&dev_base_lock);		return -ENODEV;	}	strcpy(ifr.ifr_name, dev->name);	read_unlock(&dev_base_lock);	if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))		return -EFAULT;	return 0;}/* *	Perform a SIOCGIFCONF call. This structure will change *	size eventually, and there is nothing I can do about it. *	Thus we will need a 'compatibility mode'. */static int dev_ifconf(struct net *net, char __user *arg){	struct ifconf ifc;	struct net_device *dev;	char __user *pos;	int len;	int total;	int i;	/*	 *	Fetch the caller's info block.	 */	if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))		return -EFAULT;	pos = ifc.ifc_buf;	len = ifc.ifc_len;	/*	 *	Loop over the interfaces, and write an info block for each.	 */	total = 0;	for_each_netdev(net, dev) {		for (i = 0; i < NPROTO; i++) {			if (gifconf_list[i]) {				int done;				if (!pos)					done = gifconf_list[i](dev, NULL, 0);				else					done = gifconf_list[i](dev, pos + total,							       len - total);				if (done < 0)					return -EFAULT;				total += done;			}		}	}	/*	 *	All done.  Write the updated control block back to the caller.	 */	ifc.ifc_len = total;	/*	 * 	Both BSD and Solaris return 0 here, so we do too.	 */	return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0;}#ifdef CONFIG_PROC_FS/* *	This is invoked by the /proc filesystem handler to display a device *	in detail. */void *dev_seq_start(struct seq_file *seq, loff_t *pos){	struct net *net = seq->private;	loff_t off;	struct net_device *dev;	read_lock(&dev_base_lock);	if (!*pos)		return SEQ_START_TOKEN;	off = 1;	for_each_netdev(net, dev)		if (off++ == *pos)			return dev;	return NULL;}void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct net *net = seq->private;	++*pos;	return v == SEQ_START_TOKEN ?		first_net_device(net) : next_net_device((struct net_device *)v);}void dev_seq_stop(struct seq_file *seq, void *v){	read_unlock(&dev_base_lock);}static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev){	struct net_device_stats *stats = dev->get_stats(dev);	seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "		   "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",		   dev->name, stats->rx_bytes, stats->rx_packets,		   stats->rx_errors,		   stats->rx_dropped + stats->rx_missed_errors,		   stats->rx_fifo_errors,		   stats->rx_length_errors + stats->rx_over_errors +		    stats->rx_crc_errors + stats->rx_frame_errors,		   stats->rx_compressed, stats->multicast,		   stats->tx_bytes, stats->tx_packets,		   stats->tx_errors, stats->tx_dropped,		   stats->tx_fifo_errors, stats->collisions,		   stats->tx_carrier_errors +		    stats->tx_aborted_errors +		    stats->tx_window_errors +		    stats->tx_heartbeat_errors,		   stats->tx_compressed);}/* *	Called from the PROCfs module. This now uses the new arbitrary sized *	/proc/net interface to create /proc/net/dev */static int dev_seq_show(struct seq_file *seq, void *v){	if (v == SEQ_START_TOKEN)		seq_puts(seq, "Inter-|   Receive                            "			      "                    |  Transmit\n"			      " face |bytes    packets errs drop fifo frame "			      "compressed multicast|bytes    packets errs "			      "drop fifo colls carrier compressed\n");	else		dev_seq_printf_stats(seq, v);	return 0;}static struct netif_rx_stats *softnet_get_online(loff_t *pos){	struct netif_rx_stats *rc = NULL;	while (*pos < NR_CPUS)		if (cpu_online(*pos)) {			rc = &per_cpu(netdev_rx_stat, *pos);			break;		} else			++*pos;	return rc;}static void *softnet_seq_start(struct seq_file *seq, loff_t *pos){	return softnet_get_online(pos);}static void *softnet_seq_next(struct seq_file *seq, void *v, loff_t *pos){	++*pos;	return softnet_get_online(pos);}static void softnet_seq_stop(struct seq_file *seq, void *v){}static int softnet_seq_show(struct seq_file *seq, void *v){	struct netif_rx_stats *s = v;	seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",		   s->total, s->dropped, s->time_squeeze, 0,		   0, 0, 0, 0, /* was fastroute */		   s->cpu_collision );	return 0;}static const struct seq_operations dev_seq_ops = {	.start = dev_seq_start,	.next  = dev_seq_next,	.stop  = dev_seq_stop,	.show  = dev_seq_show,};static int dev_seq_open(struct inode *inode, struct file *file){	struct seq_file *seq;	int res;	res =  seq_open(file, &dev_seq_ops);	if (!res) {		seq = file->private_data;		seq->private = get_proc_net(inode);		if (!seq->private) {			seq_release(inode, file);			res = -ENXIO;		}	}	return res;}static int dev_seq_release(struct inode *inode, struct file *file){	struct seq_file *seq = file->private_data;	struct net *net = seq->private;	put_net(net);	return seq_release(inode, file);}static const struct file_operations dev_seq_fops = {	.owner	 = THIS_MODULE,	.open    = dev_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = dev_seq_release,};static const struct seq_operations softnet_seq_ops = {	.start = softnet_seq_start,	.next  = softnet_seq_next,	.stop  = softnet_seq_stop,	.show  = softnet_seq_show,};static int softnet_seq_open(struct inode *inode, struct file *file){	return seq_open(file, &softnet_seq_ops);}static const struct file_operations softnet_seq_fops = {	.owner	 = THIS_MODULE,	.open    = softnet_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release,};static void *ptype_get_idx(loff_t pos){	struct packet_type *pt = NULL;	loff_t i = 0;	int t;	list_for_each_entry_rcu(pt, &ptype_all, list) {		if (i == pos)			return pt;		++i;	}	for (t = 0; t < 16; t++) {		list_for_each_entry_rcu(pt, &ptype_base[t], list) {			if (i == pos)				return pt;			++i;		}	}	return NULL;}static void *ptype_seq_start(struct seq_file *seq, loff_t *pos){	rcu_read_lock();	return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN;}static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos){	struct packet_type *pt;	struct list_head *nxt;	int hash;	++*pos;	if (v == SEQ_START_TOKEN)		return ptype_get_idx(0);	pt = v;	nxt = pt->list.next;	if (pt->type == htons(ETH_P_ALL)) {		if (nxt != &ptype_all)			goto found;		hash = 0;		nxt = ptype_base[0].next;	} else		hash = ntohs(pt->type) & 15;	while (nxt == &ptype_base[hash]) {		if (++hash >= 16)			return NULL;		nxt = ptype_base[hash].next;	}found:	return list_entry(nxt, struct packet_type, list);}static void ptype_seq_stop(struct seq_file *seq, void *v){	rcu_read_unlock();}static void ptype_seq_decode(struct seq_file *seq, void *sym){#ifdef CONFIG_KALLSYMS	unsigned long offset = 0, symsize;	const char *symname;	char *modname;	char namebuf[128];	symname = kallsyms_lookup((unsigned long)sym, &symsize, &offset,				  &modname, namebuf);	if (sym

⌨️ 快捷键说明

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