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

📄 dev.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (dev->master) {		skb->real_dev = skb->dev;		skb->dev = dev->master;	}}static void net_tx_action(struct softirq_action *h){	struct softnet_data *sd = &__get_cpu_var(softnet_data);	if (sd->completion_queue) {		struct sk_buff *clist;		local_irq_disable();		clist = sd->completion_queue;		sd->completion_queue = NULL;		local_irq_enable();		while (clist) {			struct sk_buff *skb = clist;			clist = clist->next;			BUG_TRAP(!atomic_read(&skb->users));			__kfree_skb(skb);		}	}	if (sd->output_queue) {		struct net_device *head;		local_irq_disable();		head = sd->output_queue;		sd->output_queue = NULL;		local_irq_enable();		while (head) {			struct net_device *dev = head;			head = head->next_sched;			smp_mb__before_clear_bit();			clear_bit(__LINK_STATE_SCHED, &dev->state);			if (spin_trylock(&dev->queue_lock)) {				qdisc_run(dev);				spin_unlock(&dev->queue_lock);			} else {				netif_schedule(dev);			}		}	}}static __inline__ int deliver_skb(struct sk_buff *skb,				  struct packet_type *pt_prev){	atomic_inc(&skb->users);	return pt_prev->func(skb, skb->dev, pt_prev);}#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);static __inline__ int handle_bridge(struct sk_buff **pskb,				    struct packet_type **pt_prev, int *ret){	struct net_bridge_port *port;	if ((*pskb)->pkt_type == PACKET_LOOPBACK ||	    (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)		return 0;	if (*pt_prev) {		*ret = deliver_skb(*pskb, *pt_prev);		*pt_prev = NULL;	} 		return br_handle_frame_hook(port, pskb);}#else#define handle_bridge(skb, pt_prev, ret)	(0)#endif#ifdef CONFIG_NET_CLS_ACT/* TODO: Maybe we should just force sch_ingress to be compiled in * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions * a compare and 2 stores extra right now if we dont have it on * but have CONFIG_NET_CLS_ACT * NOTE: This doesnt stop any functionality; if you dont have  * the ingress scheduler, you just cant add policies on ingress. * */int ing_filter(struct sk_buff *skb) {	struct Qdisc *q;	struct net_device *dev = skb->dev;	int result = TC_ACT_OK;		if (dev->qdisc_ingress) {		__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);		if (MAX_RED_LOOP < ttl++) {			printk("Redir loop detected Dropping packet (%s->%s)\n",				skb->input_dev?skb->input_dev->name:"??",skb->dev->name);			return TC_ACT_SHOT;		}		skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl);		skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);		if (NULL == skb->input_dev) {			skb->input_dev = skb->dev;			printk("ing_filter:  fixed  %s out %s\n",skb->input_dev->name,skb->dev->name);		}		spin_lock(&dev->ingress_lock);		if ((q = dev->qdisc_ingress) != NULL)			result = q->enqueue(skb, q);		spin_unlock(&dev->ingress_lock);	}	return result;}#endifint netif_receive_skb(struct sk_buff *skb){	struct packet_type *ptype, *pt_prev;	int ret = NET_RX_DROP;	unsigned short type;#ifdef CONFIG_NETPOLL	if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {		kfree_skb(skb);		return NET_RX_DROP;	}#endif	if (!skb->stamp.tv_sec)		net_timestamp(&skb->stamp);	skb_bond(skb);	__get_cpu_var(netdev_rx_stat).total++;	skb->h.raw = skb->nh.raw = skb->data;	skb->mac_len = skb->nh.raw - skb->mac.raw;	pt_prev = NULL;	rcu_read_lock();#ifdef CONFIG_NET_CLS_ACT	if (skb->tc_verd & TC_NCLS) {		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);		goto ncls;	}#endif	list_for_each_entry_rcu(ptype, &ptype_all, list) {		if (!ptype->dev || ptype->dev == skb->dev) {			if (pt_prev) 				ret = deliver_skb(skb, pt_prev);			pt_prev = ptype;		}	}#ifdef CONFIG_NET_CLS_ACT	if (pt_prev) {		ret = deliver_skb(skb, pt_prev);		pt_prev = NULL; /* noone else should process this after*/	} else {		skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);	}	ret = ing_filter(skb);	if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {		kfree_skb(skb);		goto out;	}	skb->tc_verd = 0;ncls:#endif	handle_diverter(skb);	if (handle_bridge(&skb, &pt_prev, &ret))		goto out;	type = skb->protocol;	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {		if (ptype->type == type &&		    (!ptype->dev || ptype->dev == skb->dev)) {			if (pt_prev) 				ret = deliver_skb(skb, pt_prev);			pt_prev = ptype;		}	}	if (pt_prev) {		ret = pt_prev->func(skb, skb->dev, pt_prev);	} 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 net_device *backlog_dev, int *budget){	int work = 0;	int quota = min(backlog_dev->quota, *budget);	struct softnet_data *queue = &__get_cpu_var(softnet_data);	unsigned long start_time = jiffies;	for (;;) {		struct sk_buff *skb;		struct net_device *dev;		local_irq_disable();		skb = __skb_dequeue(&queue->input_pkt_queue);		if (!skb)			goto job_done;		local_irq_enable();		dev = skb->dev;		netif_receive_skb(skb);		dev_put(dev);		work++;		if (work >= quota || jiffies - start_time > 1)			break;#ifdef CONFIG_NET_HW_FLOWCONTROL		if (queue->throttle &&		    queue->input_pkt_queue.qlen < no_cong_thresh ) {			queue->throttle = 0;			if (atomic_dec_and_test(&netdev_dropping)) {				netdev_wakeup();				break;			}		}#endif	}	backlog_dev->quota -= work;	*budget -= work;	return -1;job_done:	backlog_dev->quota -= work;	*budget -= work;	list_del(&backlog_dev->poll_list);	smp_mb__before_clear_bit();	netif_poll_enable(backlog_dev);	if (queue->throttle) {		queue->throttle = 0;#ifdef CONFIG_NET_HW_FLOWCONTROL		if (atomic_dec_and_test(&netdev_dropping))			netdev_wakeup();#endif	}	local_irq_enable();	return 0;}static void net_rx_action(struct softirq_action *h){	struct softnet_data *queue = &__get_cpu_var(softnet_data);	unsigned long start_time = jiffies;	int budget = netdev_max_backlog;		local_irq_disable();	while (!list_empty(&queue->poll_list)) {		struct net_device *dev;		if (budget <= 0 || jiffies - start_time > 1)			goto softnet_break;		local_irq_enable();		dev = list_entry(queue->poll_list.next,				 struct net_device, poll_list);		if (dev->quota <= 0 || dev->poll(dev, &budget)) {			local_irq_disable();			list_del(&dev->poll_list);			list_add_tail(&dev->poll_list, &queue->poll_list);			if (dev->quota < 0)				dev->quota += dev->weight;			else				dev->quota = dev->weight;		} else {			dev_put(dev);			local_irq_disable();		}	}out:	local_irq_enable();	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 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(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(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 (dev = dev_base; dev; dev = dev->next) {		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. */static __inline__ struct net_device *dev_get_idx(loff_t pos){	struct net_device *dev;	loff_t i;	for (i = 0, dev = dev_base; dev && i < pos; ++i, dev = dev->next);	return i == pos ? dev : NULL;}void *dev_seq_start(struct seq_file *seq, loff_t *pos){	read_lock(&dev_base_lock);	return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;}void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos){	++*pos;	return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next;}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){	if (dev->get_stats) {		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);	} else		seq_printf(seq, "%6s: No statistics available.\n", dev->name);}/* *	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;

⌨️ 快捷键说明

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