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

📄 pktgen.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		len = num_arg(&user_buffer[i], 5, &value);		if (len < 0) {			return len;		}		i += len;		pkt_dev->queue_map_max = value;		sprintf(pg_result, "OK: queue_map_max=%u", pkt_dev->queue_map_max);		return count;	}	if (!strcmp(name, "mpls")) {		unsigned n, cnt;		len = get_labels(&user_buffer[i], pkt_dev);		if (len < 0)			return len;		i += len;		cnt = sprintf(pg_result, "OK: mpls=");		for (n = 0; n < pkt_dev->nr_labels; n++)			cnt += sprintf(pg_result + cnt,				       "%08x%s", ntohl(pkt_dev->labels[n]),				       n == pkt_dev->nr_labels-1 ? "" : ",");		if (pkt_dev->nr_labels && pkt_dev->vlan_id != 0xffff) {			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */			pkt_dev->svlan_id = 0xffff;			if (debug)				printk(KERN_DEBUG "pktgen: VLAN/SVLAN auto turned off\n");		}		return count;	}	if (!strcmp(name, "vlan_id")) {		len = num_arg(&user_buffer[i], 4, &value);		if (len < 0) {			return len;		}		i += len;		if (value <= 4095) {			pkt_dev->vlan_id = value;  /* turn on VLAN */			if (debug)				printk(KERN_DEBUG "pktgen: VLAN turned on\n");			if (debug && pkt_dev->nr_labels)				printk(KERN_DEBUG "pktgen: MPLS auto turned off\n");			pkt_dev->nr_labels = 0;    /* turn off MPLS */			sprintf(pg_result, "OK: vlan_id=%u", pkt_dev->vlan_id);		} else {			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */			pkt_dev->svlan_id = 0xffff;			if (debug)				printk(KERN_DEBUG "pktgen: VLAN/SVLAN turned off\n");		}		return count;	}	if (!strcmp(name, "vlan_p")) {		len = num_arg(&user_buffer[i], 1, &value);		if (len < 0) {			return len;		}		i += len;		if ((value <= 7) && (pkt_dev->vlan_id != 0xffff)) {			pkt_dev->vlan_p = value;			sprintf(pg_result, "OK: vlan_p=%u", pkt_dev->vlan_p);		} else {			sprintf(pg_result, "ERROR: vlan_p must be 0-7");		}		return count;	}	if (!strcmp(name, "vlan_cfi")) {		len = num_arg(&user_buffer[i], 1, &value);		if (len < 0) {			return len;		}		i += len;		if ((value <= 1) && (pkt_dev->vlan_id != 0xffff)) {			pkt_dev->vlan_cfi = value;			sprintf(pg_result, "OK: vlan_cfi=%u", pkt_dev->vlan_cfi);		} else {			sprintf(pg_result, "ERROR: vlan_cfi must be 0-1");		}		return count;	}	if (!strcmp(name, "svlan_id")) {		len = num_arg(&user_buffer[i], 4, &value);		if (len < 0) {			return len;		}		i += len;		if ((value <= 4095) && ((pkt_dev->vlan_id != 0xffff))) {			pkt_dev->svlan_id = value;  /* turn on SVLAN */			if (debug)				printk(KERN_DEBUG "pktgen: SVLAN turned on\n");			if (debug && pkt_dev->nr_labels)				printk(KERN_DEBUG "pktgen: MPLS auto turned off\n");			pkt_dev->nr_labels = 0;    /* turn off MPLS */			sprintf(pg_result, "OK: svlan_id=%u", pkt_dev->svlan_id);		} else {			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */			pkt_dev->svlan_id = 0xffff;			if (debug)				printk(KERN_DEBUG "pktgen: VLAN/SVLAN turned off\n");		}		return count;	}	if (!strcmp(name, "svlan_p")) {		len = num_arg(&user_buffer[i], 1, &value);		if (len < 0) {			return len;		}		i += len;		if ((value <= 7) && (pkt_dev->svlan_id != 0xffff)) {			pkt_dev->svlan_p = value;			sprintf(pg_result, "OK: svlan_p=%u", pkt_dev->svlan_p);		} else {			sprintf(pg_result, "ERROR: svlan_p must be 0-7");		}		return count;	}	if (!strcmp(name, "svlan_cfi")) {		len = num_arg(&user_buffer[i], 1, &value);		if (len < 0) {			return len;		}		i += len;		if ((value <= 1) && (pkt_dev->svlan_id != 0xffff)) {			pkt_dev->svlan_cfi = value;			sprintf(pg_result, "OK: svlan_cfi=%u", pkt_dev->svlan_cfi);		} else {			sprintf(pg_result, "ERROR: svlan_cfi must be 0-1");		}		return count;	}	if (!strcmp(name, "tos")) {		__u32 tmp_value = 0;		len = hex32_arg(&user_buffer[i], 2, &tmp_value);		if (len < 0) {			return len;		}		i += len;		if (len == 2) {			pkt_dev->tos = tmp_value;			sprintf(pg_result, "OK: tos=0x%02x", pkt_dev->tos);		} else {			sprintf(pg_result, "ERROR: tos must be 00-ff");		}		return count;	}	if (!strcmp(name, "traffic_class")) {		__u32 tmp_value = 0;		len = hex32_arg(&user_buffer[i], 2, &tmp_value);		if (len < 0) {			return len;		}		i += len;		if (len == 2) {			pkt_dev->traffic_class = tmp_value;			sprintf(pg_result, "OK: traffic_class=0x%02x", pkt_dev->traffic_class);		} else {			sprintf(pg_result, "ERROR: traffic_class must be 00-ff");		}		return count;	}	sprintf(pkt_dev->result, "No such parameter \"%s\"", name);	return -EINVAL;}static int pktgen_if_open(struct inode *inode, struct file *file){	return single_open(file, pktgen_if_show, PDE(inode)->data);}static const struct file_operations pktgen_if_fops = {	.owner   = THIS_MODULE,	.open    = pktgen_if_open,	.read    = seq_read,	.llseek  = seq_lseek,	.write   = pktgen_if_write,	.release = single_release,};static int pktgen_thread_show(struct seq_file *seq, void *v){	struct pktgen_thread *t = seq->private;	struct pktgen_dev *pkt_dev;	BUG_ON(!t);	seq_printf(seq, "Running: ");	if_lock(t);	list_for_each_entry(pkt_dev, &t->if_list, list)		if (pkt_dev->running)			seq_printf(seq, "%s ", pkt_dev->odev->name);	seq_printf(seq, "\nStopped: ");	list_for_each_entry(pkt_dev, &t->if_list, list)		if (!pkt_dev->running)			seq_printf(seq, "%s ", pkt_dev->odev->name);	if (t->result[0])		seq_printf(seq, "\nResult: %s\n", t->result);	else		seq_printf(seq, "\nResult: NA\n");	if_unlock(t);	return 0;}static ssize_t pktgen_thread_write(struct file *file,				   const char __user * user_buffer,				   size_t count, loff_t * offset){	struct seq_file *seq = (struct seq_file *)file->private_data;	struct pktgen_thread *t = seq->private;	int i = 0, max, len, ret;	char name[40];	char *pg_result;	if (count < 1) {		//      sprintf(pg_result, "Wrong command format");		return -EINVAL;	}	max = count - i;	len = count_trail_chars(&user_buffer[i], max);	if (len < 0)		return len;	i += len;	/* Read variable name */	len = strn_len(&user_buffer[i], sizeof(name) - 1);	if (len < 0)		return len;	memset(name, 0, sizeof(name));	if (copy_from_user(name, &user_buffer[i], len))		return -EFAULT;	i += len;	max = count - i;	len = count_trail_chars(&user_buffer[i], max);	if (len < 0)		return len;	i += len;	if (debug)		printk(KERN_DEBUG "pktgen: t=%s, count=%lu\n",		       name, (unsigned long)count);	if (!t) {		printk(KERN_ERR "pktgen: ERROR: No thread\n");		ret = -EINVAL;		goto out;	}	pg_result = &(t->result[0]);	if (!strcmp(name, "add_device")) {		char f[32];		memset(f, 0, 32);		len = strn_len(&user_buffer[i], sizeof(f) - 1);		if (len < 0) {			ret = len;			goto out;		}		if (copy_from_user(f, &user_buffer[i], len))			return -EFAULT;		i += len;		mutex_lock(&pktgen_thread_lock);		pktgen_add_device(t, f);		mutex_unlock(&pktgen_thread_lock);		ret = count;		sprintf(pg_result, "OK: add_device=%s", f);		goto out;	}	if (!strcmp(name, "rem_device_all")) {		mutex_lock(&pktgen_thread_lock);		t->control |= T_REMDEVALL;		mutex_unlock(&pktgen_thread_lock);		schedule_timeout_interruptible(msecs_to_jiffies(125));	/* Propagate thread->control  */		ret = count;		sprintf(pg_result, "OK: rem_device_all");		goto out;	}	if (!strcmp(name, "max_before_softirq")) {		sprintf(pg_result, "OK: Note! max_before_softirq is obsoleted -- Do not use");		ret = count;		goto out;	}	ret = -EINVAL;out:	return ret;}static int pktgen_thread_open(struct inode *inode, struct file *file){	return single_open(file, pktgen_thread_show, PDE(inode)->data);}static const struct file_operations pktgen_thread_fops = {	.owner   = THIS_MODULE,	.open    = pktgen_thread_open,	.read    = seq_read,	.llseek  = seq_lseek,	.write   = pktgen_thread_write,	.release = single_release,};/* Think find or remove for NN */static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove){	struct pktgen_thread *t;	struct pktgen_dev *pkt_dev = NULL;	list_for_each_entry(t, &pktgen_threads, th_list) {		pkt_dev = pktgen_find_dev(t, ifname);		if (pkt_dev) {			if (remove) {				if_lock(t);				pkt_dev->removal_mark = 1;				t->control |= T_REMDEV;				if_unlock(t);			}			break;		}	}	return pkt_dev;}/* * mark a device for removal */static void pktgen_mark_device(const char *ifname){	struct pktgen_dev *pkt_dev = NULL;	const int max_tries = 10, msec_per_try = 125;	int i = 0;	mutex_lock(&pktgen_thread_lock);	pr_debug("pktgen: pktgen_mark_device marking %s for removal\n", ifname);	while (1) {		pkt_dev = __pktgen_NN_threads(ifname, REMOVE);		if (pkt_dev == NULL)			break;	/* success */		mutex_unlock(&pktgen_thread_lock);		pr_debug("pktgen: pktgen_mark_device waiting for %s "				"to disappear....\n", ifname);		schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));		mutex_lock(&pktgen_thread_lock);		if (++i >= max_tries) {			printk(KERN_ERR "pktgen_mark_device: timed out after "			       "waiting %d msec for device %s to be removed\n",			       msec_per_try * i, ifname);			break;		}	}	mutex_unlock(&pktgen_thread_lock);}static void pktgen_change_name(struct net_device *dev){	struct pktgen_thread *t;	list_for_each_entry(t, &pktgen_threads, th_list) {		struct pktgen_dev *pkt_dev;		list_for_each_entry(pkt_dev, &t->if_list, list) {			if (pkt_dev->odev != dev)				continue;			remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);			pkt_dev->entry = create_proc_entry(dev->name, 0600,							   pg_proc_dir);			if (!pkt_dev->entry)				printk(KERN_ERR "pktgen: can't move proc "				       " entry for '%s'\n", dev->name);			break;		}	}}static int pktgen_device_event(struct notifier_block *unused,			       unsigned long event, void *ptr){	struct net_device *dev = ptr;	if (dev->nd_net != &init_net)		return NOTIFY_DONE;	/* It is OK that we do not hold the group lock right now,	 * as we run under the RTNL lock.	 */	switch (event) {	case NETDEV_CHANGENAME:		pktgen_change_name(dev);		break;	case NETDEV_UNREGISTER:		pktgen_mark_device(dev->name);		break;	}	return NOTIFY_DONE;}/* Associate pktgen_dev with a device. */static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname){	struct net_device *odev;	int err;	/* Clean old setups */	if (pkt_dev->odev) {		dev_put(pkt_dev->odev);		pkt_dev->odev = NULL;	}	odev = dev_get_by_name(&init_net, ifname);	if (!odev) {		printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname);		return -ENODEV;	}	if (odev->type != ARPHRD_ETHER) {		printk(KERN_ERR "pktgen: not an ethernet device: \"%s\"\n", ifname);		err = -EINVAL;	} else if (!netif_running(odev)) {		printk(KERN_ERR "pktgen: device is down: \"%s\"\n", ifname);		err = -ENETDOWN;	} else {		pkt_dev->odev = odev;		return 0;	}	dev_put(odev);	return err;}/* Read pkt_dev from the interface and set up internal pktgen_dev * structure to have the right information to create/send packets */static void pktgen_setup_inject(struct pktgen_dev *pkt_dev){	if (!pkt_dev->odev) {		printk(KERN_ERR "pktgen: ERROR: pkt_dev->odev == NULL in "		       "setup_inject.\n");		sprintf(pkt_dev->result,			"ERROR: pkt_dev->odev == NULL in setup_inject.\n");		return;	}	/* Default to the interface's mac if not explicitly set. */	if (is_zero_ether_addr(pkt_dev->src_mac))		memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN);	/* Set up Dest MAC */	memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);	/* Set up pkt size */	pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;	if (pkt_dev->flags & F_IPV6) {		/*		 * Skip this automatic address setting until locks or functions		 * gets exported		 */#ifdef NOTNOW		int i, set = 0, err = 1;		struct inet6_dev *idev;		for (i = 0; i < IN6_ADDR_HSIZE; i++)			if (pkt_dev->cur_in6_saddr.s6_addr[i]) {				set = 1;				break;			}		if (!set) {			/*			 * Use linklevel address if unconfigured.			 *			 * use ipv6_get_lladdr if/when it's get exported

⌨️ 快捷键说明

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