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

📄 dev.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		netdev_fc_slots[bit].stimul = NULL;		netdev_fc_slots[bit].dev = NULL;		clear_bit(bit, &netdev_fc_mask);		clear_bit(bit, &netdev_fc_xoff);	}	restore_flags(flags);}static void netdev_wakeup(void){	unsigned long xoff;	cli();	xoff = netdev_fc_xoff;	netdev_fc_xoff = 0;	netdev_dropping = 0;	netdev_throttle_events++;	while (xoff) {		int i = ffz(~xoff);		xoff &= ~(1<<i);		netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);	}	sti();}#endifstatic void dev_clear_backlog(struct device *dev){	struct sk_buff *curr;	unsigned long flags;	/*	 *	 *  Let now clear backlog queue. -AS	 *	 *  We are competing here both with netif_rx() and net_bh().	 *  We don't want either of those to mess with skb ptrs	 *  while we work on them, thus we must grab the	 *  skb_queue_lock.	 */	if (backlog.qlen) {	repeat:		spin_lock_irqsave(&skb_queue_lock, flags);		for (curr = backlog.next;		     curr != (struct sk_buff *)(&backlog);		     curr = curr->next)			if (curr->dev == dev)			{				__skb_unlink(curr, &backlog);				spin_unlock_irqrestore(&skb_queue_lock, flags);				kfree_skb(curr);				goto repeat;			}		spin_unlock_irqrestore(&skb_queue_lock, flags);#ifdef CONFIG_NET_HW_FLOWCONTROL		if (netdev_dropping)			netdev_wakeup();#else		netdev_dropping = 0;#endif	}}/* *	Receive a packet from a device driver and queue it for the upper *	(protocol) levels.  It always succeeds. */void netif_rx(struct sk_buff *skb){#ifndef CONFIG_CPU_IS_SLOW	if(skb->stamp.tv_sec==0)		get_fast_time(&skb->stamp);#else	skb->stamp = xtime;#endif	/* The code is rearranged so that the path is the most	   short when CPU is congested, but is still operating.	 */	if (backlog.qlen <= netdev_max_backlog) {		if (backlog.qlen) {			if (netdev_dropping == 0) {				skb_queue_tail(&backlog,skb);				mark_bh(NET_BH);				return;			}			atomic_inc(&netdev_rx_dropped);			kfree_skb(skb);			return;		}#ifdef CONFIG_NET_HW_FLOWCONTROL		if (netdev_dropping)			netdev_wakeup();#else		netdev_dropping = 0;#endif		skb_queue_tail(&backlog,skb);		mark_bh(NET_BH);		return;	}	netdev_dropping = 1;	atomic_inc(&netdev_rx_dropped);	kfree_skb(skb);}#ifdef CONFIG_BRIDGEstatic inline void handle_bridge(struct sk_buff *skb, unsigned short type){	/*	 * The br_stats.flags is checked here to save the expense of a	 * function call.	 */	if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))	{		/*		 *	We pass the bridge a complete frame. This means		 *	recovering the MAC header first.		 */		int offset;		skb=skb_clone(skb, GFP_ATOMIC);		if(skb==NULL)			return;		offset=skb->data-skb->mac.raw;		skb_push(skb,offset);	/* Put header back on for bridge */		if(br_receive_frame(skb))			return;		kfree_skb(skb);	}	return;}#endif/* *	When we are called the queue is ready to grab, the interrupts are *	on and hardware can interrupt and queue to the receive queue as we *	run with no problems. *	This is run as a bottom half after an interrupt handler that does *	mark_bh(NET_BH); */void net_bh(void){	struct packet_type *ptype;	struct packet_type *pt_prev;	unsigned short type;#ifndef _HURD_	unsigned long start_time = jiffies;#ifdef CONFIG_CPU_IS_SLOW	static unsigned long start_busy = 0;	static unsigned long ave_busy = 0;	if (start_busy == 0)		start_busy = start_time;	net_cpu_congestion = ave_busy>>8;#endif#endif	NET_PROFILE_ENTER(net_bh);	/*	 *	Can we send anything now? We want to clear the	 *	decks for any more sends that get done as we	 *	process the input. This also minimises the	 *	latency on a transmit interrupt bh.	 */	if (qdisc_head.forw != &qdisc_head)		qdisc_run_queues();	/*	 *	Any data left to process. This may occur because a	 *	mark_bh() is done after we empty the queue including	 *	that from the device which does a mark_bh() just after	 */	/*	 *	While the queue is not empty..	 *	 *	Note that the queue never shrinks due to	 *	an interrupt, so we can do this test without	 *	disabling interrupts.	 */	while (!skb_queue_empty(&backlog))	{		struct sk_buff * skb;#ifndef _HURD_		/* Give chance to other bottom halves to run */		if (jiffies - start_time > 1)			goto net_bh_break;#endif		/*		 *	We have a packet. Therefore the queue has shrunk		 */		skb = skb_dequeue(&backlog);#ifndef _HURD_#ifdef CONFIG_CPU_IS_SLOW		if (ave_busy > 128*16) {			kfree_skb(skb);			while ((skb = skb_dequeue(&backlog)) != NULL)				kfree_skb(skb);			break;		}#endif#endif#if 0		NET_PROFILE_SKB_PASSED(skb, net_bh_skb);#endif#ifdef CONFIG_NET_FASTROUTE		if (skb->pkt_type == PACKET_FASTROUTE) {			dev_queue_xmit(skb);			continue;		}#endif		/*	 	 *	Bump the pointer to the next structure.		 *		 *	On entry to the protocol layer. skb->data and		 *	skb->nh.raw point to the MAC and encapsulated data		 */		/* XXX until we figure out every place to modify.. */		skb->h.raw = skb->nh.raw = skb->data;		if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {			printk(KERN_CRIT "%s: wrong mac.raw ptr, proto=%04x\n", skb->dev->name, skb->protocol);			kfree_skb(skb);			continue;		}		/*		 * 	Fetch the packet protocol ID.		 */		type = skb->protocol;#ifdef CONFIG_BRIDGE		/*		 *	If we are bridging then pass the frame up to the		 *	bridging code (if this protocol is to be bridged).		 *      If it is bridged then move on		 */		handle_bridge(skb, type);#endif		/*		 *	We got a packet ID.  Now loop over the "known protocols"		 * 	list. There are two lists. The ptype_all list of taps (normally empty)		 *	and the main protocol list which is hashed perfectly for normal protocols.		 */		pt_prev = NULL;		for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)		{			if (!ptype->dev || ptype->dev == skb->dev) {				if(pt_prev)				{					struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);					if(skb2)						pt_prev->func(skb2,skb->dev, pt_prev);				}				pt_prev=ptype;			}		}		for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)		{			if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))			{				/*				 *	We already have a match queued. Deliver				 *	to it and then remember the new match				 */				if(pt_prev)				{					struct sk_buff *skb2;					skb2=skb_clone(skb, GFP_ATOMIC);					/*					 *	Kick the protocol handler. This should be fast					 *	and efficient code.					 */					if(skb2)						pt_prev->func(skb2, skb->dev, pt_prev);				}				/* Remember the current last to do */				pt_prev=ptype;			}		} /* End of protocol list loop */		/*		 *	Is there a last item to send to ?		 */		if(pt_prev)			pt_prev->func(skb, skb->dev, pt_prev);		/*		 * 	Has an unknown packet has been received ?		 */		else {			kfree_skb(skb);		}  	}	/* End of queue loop */  	/*  	 *	We have emptied the queue  	 */	/*	 *	One last output flush.	 */	if (qdisc_head.forw != &qdisc_head)		qdisc_run_queues();#ifndef _HURD_#ifdef  CONFIG_CPU_IS_SLOW        if (1) {		unsigned long start_idle = jiffies;		ave_busy += ((start_idle - start_busy)<<3) - (ave_busy>>4);		start_busy = 0;	}#endif#endif#ifdef CONFIG_NET_HW_FLOWCONTROL	if (netdev_dropping)		netdev_wakeup();#else	netdev_dropping = 0;#endif	NET_PROFILE_LEAVE(net_bh);	return;#ifndef _HURD_net_bh_break:	mark_bh(NET_BH);	NET_PROFILE_LEAVE(net_bh);	return;#endif}/* Protocol dependent address dumping routines */static gifconf_func_t * gifconf_list [NPROTO];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) *//* *	This call is useful, but I'd remove it too. * *	The reason is purely aestetical, it is the only call *	from SIOC* family using struct ifreq in reversed manner. *	Besides that, it is pretty silly to put "drawing" facility *	to kernel, it is useful only to print ifindices *	in readable form, is not it? --ANK * *	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 *arg){	struct device *dev;	struct ifreq ifr;	int err;	/*	 *	Fetch the caller's info block.	 */	err = copy_from_user(&ifr, arg, sizeof(struct ifreq));	if (err)		return -EFAULT;	dev = dev_get_by_index(ifr.ifr_ifindex);	if (!dev)		return -ENODEV;	strcpy(ifr.ifr_name, dev->name);	err = copy_to_user(arg, &ifr, sizeof(struct ifreq));	return (err)?-EFAULT: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'. */#ifdef _HURD_int dev_ifconf(char *arg)#elsestatic int dev_ifconf(char *arg)#endif{	struct ifconf ifc;	struct device *dev;	char *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 != NULL; dev = dev->next) {		for (i=0; i<NPROTO; i++) {			if (gifconf_list[i]) {				int done;				if (pos==NULL) {					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;	if (copy_to_user(arg, &ifc, sizeof(struct ifconf)))		return -EFAULT;	/*	 * 	Both BSD and Solaris return 0 here, so we do too.	 */	return 0;}/* *	This is invoked by the /proc filesystem handler to display a device *	in detail. */#ifdef CONFIG_PROC_FSstatic int sprintf_stats(char *buffer, struct device *dev){	struct net_device_stats *stats = (dev->get_stats ? dev->get_stats(dev): NULL);	int size;	if (stats)		size = sprintf(buffer, "%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		size = sprintf(buffer, "%6s: No statistics available.\n", dev->name);	return size;}/* *	Called from the PROCfs module. This now uses the new arbitrary sized /proc/net interface *	to create /proc/net/dev */int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy){	int len=0;	off_t begin=0;	off_t pos=0;	int size;	struct device *dev;	size = sprintf(buffer,		"Inter-|   Receive                                                |  Transmit\n"		" face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed\n");	pos+=size;	len+=size;	for (dev = dev_base; dev != NULL; dev = dev->next)	{		size = sprintf_stats(buffer+len, dev);		len+=size;		pos=begin+len;		if(pos<offset)		{			len=0;			begin=pos;		}		if(pos>offset+length)			break;	}	*start=buffer+(offset-begin);	/* Start of wanted data */	len-=(offset-begin);		/* Start slop */	if(len>length)		len=length;		/* Ending slop */	return len;}static int dev_proc_stats(char *buffer, char **start, off_t offset,			  int length, int *eof, void *data){	int len;	len = sprintf(buffer, "%08x %08x %08x %08x %08x\n",		      atomic_read(&netdev_rx_dropped),#ifdef CONFIG_NET_HW_FLOWCONTROL		      netdev_throttle_events,#else		      0,#endif#ifdef CONFIG_NET_FASTROUTE		      dev_fastroute_stat.hits,		      dev_fastroute_stat.succeed,		      dev_fastroute_stat.deferred#else		      0, 0, 0#endif		      );	len -= offset;	if (len > length)		len = length;	if(len < 0)		len = 0;	*start = buffer + offset;	*eof = 1;	return len;}#endif	/* CONFIG_PROC_FS */#ifdef CONFIG_NET_RADIO#ifdef CONFIG_PROC_FS/* * Print one entry of /proc/net/wireless * This is a clone of /proc/net/dev (just above) */static int sprintf_wireless_stats(char *buffer, struct device *dev){	/* Get stats from the driver */	struct iw_statistics *stats = (dev->get_wireless_stats ?				       dev->get_wireless_stats(dev) :				       (struct iw_statistics *) NULL);	int size;	if(stats != (struct iw_statistics *) NULL)	{		size = sprintf(buffer,			       "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d\n",			       dev->name,			       stats->status,			       stats->qual.qual,			       stats->qual.updated & 1 ? '.' : ' ',			       stats->qual.level,			       stats->qual.updated & 2 ? '.' : ' ',			       stats->qual.noise,			       stats->qual.updated & 4 ? '.' : ' ',			       stats->discard.nwid,			       stats->discard.code,			       stats->discard.misc);		stats->qual.updated = 0;	}	else		size = 0;	return size;}/* * Print info for /proc/net/wireless (print all entries) * This is a clone of /proc/net/dev (just above) */int dev_get_wireless_info(char * buffer, char **start, off_t offset,			  int length, int dummy){	int		len = 0;	off_t		begin = 0;	off_t		pos = 0;	int		size;	struct device *	dev;	size = sprintf(buffer,		       "Inter-| sta-|   Quality        |   Discarded packets\n"		       " face | tus | link level noise |  nwid  crypt   misc\n"			);	pos+=size;	len+=size;	for(dev = dev_base; dev != NULL; dev = dev->next)	{		size = sprintf_wireless_stats(buffer+len, dev);		len+=size;		pos=begin+len;		if(pos < offset)		{			len=0;			begin=pos;		}		if(pos > offset + length)			break;	}	*start = buffer + (offset - begin);	/* Start of wanted data */	len -= (offset - begin);		/* Start slop */	if(len > length)		len = length;		/* Ending slop */	return len;}#endif	/* CONFIG_PROC_FS */#endif	/* CONFIG_NET_RADIO */void dev_set_promiscuity(struct device *dev, int inc){	unsigned short old_flags = dev->flags;	dev->flags |= IFF_PROMISC;	if ((dev->promiscuity += inc) == 0)		dev->flags &= ~IFF_PROMISC;	if (dev->flags^old_flags) {#ifdef CONFIG_NET_FASTROUTE		if (dev->flags&IFF_PROMISC) {			netdev_fastroute_obstacles++;			dev_clear_fastroute(dev);		} else			netdev_fastroute_obstacles--;#endif

⌨️ 快捷键说明

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