diff options
Diffstat (limited to 'net/core/pktgen.c')
| -rw-r--r-- | net/core/pktgen.c | 222 | 
1 files changed, 44 insertions, 178 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index aeeece72b72..f76079cd750 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -156,6 +156,7 @@  #include <linux/wait.h>  #include <linux/etherdevice.h>  #include <linux/kthread.h> +#include <linux/prefetch.h>  #include <net/net_namespace.h>  #include <net/checksum.h>  #include <net/ipv6.h> @@ -449,7 +450,6 @@ static void pktgen_stop(struct pktgen_thread *t);  static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);  static unsigned int scan_ip6(const char *s, char ip[16]); -static unsigned int fmt_ip6(char *s, const char ip[16]);  /* Module parameters, defaults. */  static int pg_count_d __read_mostly = 1000; @@ -556,21 +556,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v)  			   pkt_dev->skb_priority);  	if (pkt_dev->flags & F_IPV6) { -		char b1[128], b2[128], b3[128]; -		fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr); -		fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr); -		fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr);  		seq_printf(seq, -			   "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, -			   b2, b3); - -		fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); -		fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); -		fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr); -		seq_printf(seq, -			   "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, -			   b2, b3); - +			   "     saddr: %pI6c  min_saddr: %pI6c  max_saddr: %pI6c\n" +			   "     daddr: %pI6c  min_daddr: %pI6c  max_daddr: %pI6c\n", +			   &pkt_dev->in6_saddr, +			   &pkt_dev->min_in6_saddr, &pkt_dev->max_in6_saddr, +			   &pkt_dev->in6_daddr, +			   &pkt_dev->min_in6_daddr, &pkt_dev->max_in6_daddr);  	} else {  		seq_printf(seq,  			   "     dst_min: %s  dst_max: %s\n", @@ -706,10 +698,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)  		   pkt_dev->cur_src_mac_offset);  	if (pkt_dev->flags & F_IPV6) { -		char b1[128], b2[128]; -		fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); -		fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); -		seq_printf(seq, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1); +		seq_printf(seq, "     cur_saddr: %pI6c  cur_daddr: %pI6c\n", +				&pkt_dev->cur_in6_saddr, +				&pkt_dev->cur_in6_daddr);  	} else  		seq_printf(seq, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",  			   pkt_dev->cur_saddr, pkt_dev->cur_daddr); @@ -1309,7 +1300,7 @@ static ssize_t pktgen_if_write(struct file *file,  		buf[len] = 0;  		scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); -		fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); +		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr);  		ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); @@ -1332,7 +1323,7 @@ static ssize_t pktgen_if_write(struct file *file,  		buf[len] = 0;  		scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); -		fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); +		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr);  		ipv6_addr_copy(&pkt_dev->cur_in6_daddr,  			       &pkt_dev->min_in6_daddr); @@ -1355,7 +1346,7 @@ static ssize_t pktgen_if_write(struct file *file,  		buf[len] = 0;  		scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); -		fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); +		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr);  		if (debug)  			printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf); @@ -1376,7 +1367,7 @@ static ssize_t pktgen_if_write(struct file *file,  		buf[len] = 0;  		scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); -		fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); +		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr);  		ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); @@ -1430,11 +1421,6 @@ static ssize_t pktgen_if_write(struct file *file,  		return count;  	}  	if (!strcmp(name, "dst_mac")) { -		char *v = valstr; -		unsigned char old_dmac[ETH_ALEN]; -		unsigned char *m = pkt_dev->dst_mac; -		memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); -  		len = strn_len(&user_buffer[i], sizeof(valstr) - 1);  		if (len < 0)  			return len; @@ -1442,35 +1428,16 @@ static ssize_t pktgen_if_write(struct file *file,  		memset(valstr, 0, sizeof(valstr));  		if (copy_from_user(valstr, &user_buffer[i], len))  			return -EFAULT; -		i += len; - -		for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) { -			int value; - -			value = hex_to_bin(*v); -			if (value >= 0) -				*m = *m * 16 + value; - -			if (*v == ':') { -				m++; -				*m = 0; -			} -		} +		if (!mac_pton(valstr, pkt_dev->dst_mac)) +			return -EINVAL;  		/* Set up Dest MAC */ -		if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) -			memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); +		memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN); -		sprintf(pg_result, "OK: dstmac"); +		sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac);  		return count;  	}  	if (!strcmp(name, "src_mac")) { -		char *v = valstr; -		unsigned char old_smac[ETH_ALEN]; -		unsigned char *m = pkt_dev->src_mac; - -		memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN); -  		len = strn_len(&user_buffer[i], sizeof(valstr) - 1);  		if (len < 0)  			return len; @@ -1478,26 +1445,13 @@ static ssize_t pktgen_if_write(struct file *file,  		memset(valstr, 0, sizeof(valstr));  		if (copy_from_user(valstr, &user_buffer[i], len))  			return -EFAULT; -		i += len; - -		for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) { -			int value; - -			value = hex_to_bin(*v); -			if (value >= 0) -				*m = *m * 16 + value; - -			if (*v == ':') { -				m++; -				*m = 0; -			} -		} +		if (!mac_pton(valstr, pkt_dev->src_mac)) +			return -EINVAL;  		/* Set up Src MAC */ -		if (compare_ether_addr(old_smac, pkt_dev->src_mac)) -			memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN); +		memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN); -		sprintf(pg_result, "OK: srcmac"); +		sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac);  		return count;  	} @@ -2514,7 +2468,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)  {  	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;  	int err = 0; -	struct iphdr *iph;  	if (!x)  		return 0; @@ -2524,7 +2477,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)  		return 0;  	spin_lock(&x->lock); -	iph = ip_hdr(skb);  	err = x->outer_mode->output(x, skb);  	if (err) @@ -2624,6 +2576,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,  	} else {  		int frags = pkt_dev->nfrags;  		int i, len; +		int frag_len;  		if (frags > MAX_SKB_FRAGS) @@ -2635,6 +2588,8 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,  		}  		i = 0; +		frag_len = (datalen/frags) < PAGE_SIZE ? +			   (datalen/frags) : PAGE_SIZE;  		while (datalen > 0) {  			if (unlikely(!pkt_dev->page)) {  				int node = numa_node_id(); @@ -2648,38 +2603,18 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,  			skb_shinfo(skb)->frags[i].page = pkt_dev->page;  			get_page(pkt_dev->page);  			skb_shinfo(skb)->frags[i].page_offset = 0; -			skb_shinfo(skb)->frags[i].size = -			    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); +			/*last fragment, fill rest of data*/ +			if (i == (frags - 1)) +				skb_shinfo(skb)->frags[i].size = +				    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); +			else +				skb_shinfo(skb)->frags[i].size = frag_len;  			datalen -= skb_shinfo(skb)->frags[i].size;  			skb->len += skb_shinfo(skb)->frags[i].size;  			skb->data_len += skb_shinfo(skb)->frags[i].size;  			i++;  			skb_shinfo(skb)->nr_frags = i;  		} - -		while (i < frags) { -			int rem; - -			if (i == 0) -				break; - -			rem = skb_shinfo(skb)->frags[i - 1].size / 2; -			if (rem == 0) -				break; - -			skb_shinfo(skb)->frags[i - 1].size -= rem; - -			skb_shinfo(skb)->frags[i] = -			    skb_shinfo(skb)->frags[i - 1]; -			get_page(skb_shinfo(skb)->frags[i].page); -			skb_shinfo(skb)->frags[i].page = -			    skb_shinfo(skb)->frags[i - 1].page; -			skb_shinfo(skb)->frags[i].page_offset += -			    skb_shinfo(skb)->frags[i - 1].size; -			skb_shinfo(skb)->frags[i].size = rem; -			i++; -			skb_shinfo(skb)->nr_frags = i; -		}  	}  	/* Stamp the time, and sequence number, @@ -2917,79 +2852,6 @@ static unsigned int scan_ip6(const char *s, char ip[16])  	return len;  } -static char tohex(char hexdigit) -{ -	return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0'; -} - -static int fmt_xlong(char *s, unsigned int i) -{ -	char *bak = s; -	*s = tohex((i >> 12) & 0xf); -	if (s != bak || *s != '0') -		++s; -	*s = tohex((i >> 8) & 0xf); -	if (s != bak || *s != '0') -		++s; -	*s = tohex((i >> 4) & 0xf); -	if (s != bak || *s != '0') -		++s; -	*s = tohex(i & 0xf); -	return s - bak + 1; -} - -static unsigned int fmt_ip6(char *s, const char ip[16]) -{ -	unsigned int len; -	unsigned int i; -	unsigned int temp; -	unsigned int compressing; -	int j; - -	len = 0; -	compressing = 0; -	for (j = 0; j < 16; j += 2) { - -#ifdef V4MAPPEDPREFIX -		if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) { -			inet_ntoa_r(*(struct in_addr *)(ip + 12), s); -			temp = strlen(s); -			return len + temp; -		} -#endif -		temp = ((unsigned long)(unsigned char)ip[j] << 8) + -		    (unsigned long)(unsigned char)ip[j + 1]; -		if (temp == 0) { -			if (!compressing) { -				compressing = 1; -				if (j == 0) { -					*s++ = ':'; -					++len; -				} -			} -		} else { -			if (compressing) { -				compressing = 0; -				*s++ = ':'; -				++len; -			} -			i = fmt_xlong(s, temp); -			len += i; -			s += i; -			if (j < 14) { -				*s++ = ':'; -				++len; -			} -		} -	} -	if (compressing) { -		*s++ = ':'; -		++len; -	} -	*s = 0; -	return len; -} -  static struct sk_buff *fill_packet_ipv6(struct net_device *odev,  					struct pktgen_dev *pkt_dev)  { @@ -3682,13 +3544,12 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)  		return -ENOMEM;  	strcpy(pkt_dev->odevname, ifname); -	pkt_dev->flows = vmalloc_node(MAX_CFLOWS * sizeof(struct flow_state), +	pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state),  				      node);  	if (pkt_dev->flows == NULL) {  		kfree(pkt_dev);  		return -ENOMEM;  	} -	memset(pkt_dev->flows, 0, MAX_CFLOWS * sizeof(struct flow_state));  	pkt_dev->removal_mark = 0;  	pkt_dev->min_pkt_size = ETH_ZLEN; @@ -3846,6 +3707,7 @@ static int __init pg_init(void)  {  	int cpu;  	struct proc_dir_entry *pe; +	int ret = 0;  	pr_info("%s", version); @@ -3856,11 +3718,10 @@ static int __init pg_init(void)  	pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops);  	if (pe == NULL) {  		pr_err("ERROR: cannot create %s procfs entry\n", PGCTRL); -		proc_net_remove(&init_net, PG_PROC_DIR); -		return -EINVAL; +		ret = -EINVAL; +		goto remove_dir;  	} -	/* Register us to receive netdevice events */  	register_netdevice_notifier(&pktgen_notifier_block);  	for_each_online_cpu(cpu) { @@ -3874,13 +3735,18 @@ static int __init pg_init(void)  	if (list_empty(&pktgen_threads)) {  		pr_err("ERROR: Initialization failed for all threads\n"); -		unregister_netdevice_notifier(&pktgen_notifier_block); -		remove_proc_entry(PGCTRL, pg_proc_dir); -		proc_net_remove(&init_net, PG_PROC_DIR); -		return -ENODEV; +		ret = -ENODEV; +		goto unregister;  	}  	return 0; + + unregister: +	unregister_netdevice_notifier(&pktgen_notifier_block); +	remove_proc_entry(PGCTRL, pg_proc_dir); + remove_dir: +	proc_net_remove(&init_net, PG_PROC_DIR); +	return ret;  }  static void __exit pg_cleanup(void)  |