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

📄 dev.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 *arg){	struct ifconf ifc;	struct net_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 net_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 */ static int dev_get_info(char *buffer, char **start, off_t offset, int length){	int len = 0;	off_t begin = 0;	off_t pos = 0;	int size;	struct net_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;		read_lock(&dev_base_lock);	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;	}	read_unlock(&dev_base_lock);	*start = buffer + (offset - begin);	/* Start of wanted data */	len -= (offset - begin);		/* Start slop */	if (len > length)		len = length;			/* Ending slop */	if (len < 0)		len = 0;	return len;}static int dev_proc_stats(char *buffer, char **start, off_t offset,			  int length, int *eof, void *data){	int i, lcpu;	int len=0;	for (lcpu=0; lcpu<smp_num_cpus; lcpu++) {		i = cpu_logical_map(lcpu);		len += sprintf(buffer+len, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",			       netdev_rx_stat[i].total,			       netdev_rx_stat[i].dropped,			       netdev_rx_stat[i].time_squeeze,			       netdev_rx_stat[i].throttled,			       netdev_rx_stat[i].fastroute_hit,			       netdev_rx_stat[i].fastroute_success,			       netdev_rx_stat[i].fastroute_defer,			       netdev_rx_stat[i].fastroute_deferred_out,#if 0			       netdev_rx_stat[i].fastroute_latency_reduction#else			       netdev_rx_stat[i].cpu_collision#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 WIRELESS_EXT#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 net_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 %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.fragment,			       stats->discard.retries,			       stats->discard.misc,			       stats->miss.beacon);		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) */static int dev_get_wireless_info(char * buffer, char **start, off_t offset,			  int length){	int		len = 0;	off_t		begin = 0;	off_t		pos = 0;	int		size;		struct net_device *	dev;	size = sprintf(buffer,		       "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"		       " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"			);		pos += size;	len += size;	read_lock(&dev_base_lock);	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;	}	read_unlock(&dev_base_lock);	*start = buffer + (offset - begin);	/* Start of wanted data */	len -= (offset - begin);		/* Start slop */	if (len > length)		len = length;			/* Ending slop */	if (len < 0)		len = 0;	return len;}#endif	/* CONFIG_PROC_FS *//* *	Allow programatic access to /proc/net/wireless even if /proc *	doesn't exist... Also more efficient... */static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr){	/* Get stats from the driver */	struct iw_statistics *stats = (dev->get_wireless_stats ?				       dev->get_wireless_stats(dev) :				       (struct iw_statistics *) NULL);	if (stats != (struct iw_statistics *) NULL) {		struct iwreq *	wrq = (struct iwreq *)ifr;		/* Copy statistics to the user buffer */		if(copy_to_user(wrq->u.data.pointer, stats,				sizeof(struct iw_statistics)))			return -EFAULT;		/* Check if we need to clear the update flag */		if(wrq->u.data.flags != 0)			stats->qual.updated = 0;		return(0);	} else		return -EOPNOTSUPP;}#endif	/* WIRELESS_EXT *//** *	netdev_set_master	-	set up master/slave pair *	@slave: slave device *	@master: new master device * *	Changes the master device of the slave. Pass %NULL to break the *	bonding. The caller must hold the RTNL semaphore. On a failure *	a negative errno code is returned. On success the reference counts *	are adjusted, %RTM_NEWLINK is sent to the routing socket and the *	function returns zero. */ int netdev_set_master(struct net_device *slave, struct net_device *master){	struct net_device *old = slave->master;	ASSERT_RTNL();	if (master) {		if (old)			return -EBUSY;		dev_hold(master);	}	br_write_lock_bh(BR_NETPROTO_LOCK);	slave->master = master;	br_write_unlock_bh(BR_NETPROTO_LOCK);	if (old)		dev_put(old);	if (master)		slave->flags |= IFF_SLAVE;	else		slave->flags &= ~IFF_SLAVE;	rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);	return 0;}/** *	dev_set_promiscuity	- update promiscuity count on a device *	@dev: device *	@inc: modifier * *	Add or remove promsicuity from a device. While the count in the device *	remains above zero the interface remains promiscuous. Once it hits zero *	the device reverts back to normal filtering operation. A negative inc *	value is used to drop promiscuity on the device. */ void dev_set_promiscuity(struct net_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		dev_mc_upload(dev);		printk(KERN_INFO "device %s %s promiscuous mode\n",		       dev->name, (dev->flags&IFF_PROMISC) ? "entered" : "left");	}}/** *	dev_set_allmulti	- update allmulti count on a device *	@dev: device *	@inc: modifier * *	Add or remove reception of all multicast frames to a device. While the *	count in the device remains above zero the interface remains listening *	to all interfaces. Once it hits zero the device reverts back to normal *	filtering operation. A negative @inc value is used to drop the counter *	when releasing a resource needing all multicasts. */void dev_set_allmulti(struct net_device *dev, int inc){	unsigned short old_flags = dev->flags;	dev->flags |= IFF_ALLMULTI;	if ((dev->allmulti += inc) == 0)		dev->flags &= ~IFF_ALLMULTI;	if (dev->flags^old_flags)		dev_mc_upload(dev);}int dev_change_flags(struct net_device *dev, unsigned flags){	int ret;	int old_flags = dev->flags;	/*	 *	Set the flags on our device.	 */	dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_NOARP|IFF_DYNAMIC|			       IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |				       (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));	/*	 *	Load in the correct multicast list now the flags have changed.	 */					dev_mc_upload(dev);	/*	 *	Have we downed the interface. We handle IFF_UP ourselves	 *	according to user attempts to set it, rather than blindly	 *	setting it.	 */	ret = 0;	if ((old_flags^flags)&IFF_UP)	/* Bit is different  ? */	{		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);		if (ret == 0) 			dev_mc_upload(dev);	}	if (dev->flags&IFF_UP &&	    ((old_flags^dev->flags)&~(IFF_UP|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);	if ((flags^dev->gflags)&IFF_PROMISC) {		int inc = (flags&IFF_PROMISC) ? +1 : -1;		dev->gflags ^= IFF_PROMISC;		dev_set_promiscuity(dev, inc);	}	/* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI	   is important. Some (broken) drivers set IFF_PROMISC, when	   IFF_ALLMULTI is requested not asking us and not reporting.	 */	if ((flags^dev->gflags)&IFF_ALLMULTI) {		int inc = (flags&IFF_ALLMULTI) ? +1 : -1;		dev->gflags ^= IFF_ALLMULTI;		dev_set_allmulti(dev, inc);	}	if (old_flags^dev->flags)		rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags^dev->flags);	return ret;}/* *	Perform the SIOCxIFxxx calls.  */ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd){	struct net_device *dev;	int err;	if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)		return -ENODEV;	switch(cmd) 	{		case SIOCGIFFLAGS:	/* Get interface flags */			ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI|IFF_RUNNING))				|(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));			if (netif_running(dev) && netif_carrier_ok(dev))				ifr->ifr_flags |= IFF_RUNNING;			return 0;		case SIOCSIFFLAGS:	/* Set interface flags */			return dev_change_flags(dev, ifr->ifr_flags);				case SIOCGIFMETRIC:	/* Get the metric on the interface (currently unused) */			ifr->ifr_metric = 0;			return 0;					case SIOCSIFMETRIC:	/* Set the metric on the interface (currently unused) */			return -EOPNOTSUPP;			case SIOCGIFMTU:	/* Get the MTU of a device */			ifr->ifr_mtu = dev->mtu;			return 0;			case SIOCSIFMTU:	/* Set the MTU of a device */			if (ifr->ifr_mtu == dev->mtu)				return 0;			/*			 *	MTU must be positive.			 */			 			if (ifr->ifr_mtu<0)				return -EINVAL;			if (!netif_device_present(dev))				return -ENODEV;			if (dev->change_mtu)				err = dev->change_mtu(dev, ifr->ifr_mtu);			else {				dev->mtu = ifr->ifr_mtu;				err = 0;			}			if (!err && dev->flags&IFF_UP)				notifier_call_chain(&netdev_chain, NETDEV_CHANGEMTU, dev);			return err;		case SIOCGIFHWADDR:			memcpy(ifr->ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN);			ifr->ifr_hwaddr.sa_family=dev->type;			return 0;						case SIOCSIFHWADDR:			if (dev->set_mac_address == NULL)				return -EOPNOTSUPP;

⌨️ 快捷键说明

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