net: pktgen: packet bursting via skb->xmit_more
This patch demonstrates the effect of delaying update of HW tailptr.
(based on earlier patch by Jesper)
burst=1 is the default. It sends one packet with xmit_more=false
burst=2 sends one packet with xmit_more=true and
        2nd copy of the same packet with xmit_more=false
burst=3 sends two copies of the same packet with xmit_more=true and
        3rd copy with xmit_more=false
Performance with ixgbe (usec 30):
burst=1  tx:9.2 Mpps
burst=2  tx:13.5 Mpps
burst=3  tx:14.5 Mpps full 10G line rate
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
	
	
This commit is contained in:
		
					parent
					
						
							
								775dd692bd
							
						
					
				
			
			
				commit
				
					
						38b2cf2982
					
				
			
		
					 2 changed files with 27 additions and 2 deletions
				
			
		|  | @ -99,6 +99,9 @@ Examples: | ||||||
| 
 | 
 | ||||||
|  pgset "clone_skb 1"     sets the number of copies of the same packet |  pgset "clone_skb 1"     sets the number of copies of the same packet | ||||||
|  pgset "clone_skb 0"     use single SKB for all transmits |  pgset "clone_skb 0"     use single SKB for all transmits | ||||||
|  |  pgset "burst 8"         uses xmit_more API to queue 8 copies of the same | ||||||
|  |                          packet and update HW tx queue tail pointer once. | ||||||
|  |                          "burst 1" is the default | ||||||
|  pgset "pkt_size 9014"   sets packet size to 9014 |  pgset "pkt_size 9014"   sets packet size to 9014 | ||||||
|  pgset "frags 5"         packet will consist of 5 fragments |  pgset "frags 5"         packet will consist of 5 fragments | ||||||
|  pgset "count 200000"    sets number of packets to send, set to zero |  pgset "count 200000"    sets number of packets to send, set to zero | ||||||
|  |  | ||||||
|  | @ -387,6 +387,7 @@ struct pktgen_dev { | ||||||
| 	u16 queue_map_min; | 	u16 queue_map_min; | ||||||
| 	u16 queue_map_max; | 	u16 queue_map_max; | ||||||
| 	__u32 skb_priority;	/* skb priority field */ | 	__u32 skb_priority;	/* skb priority field */ | ||||||
|  | 	unsigned int burst;	/* number of duplicated packets to burst */ | ||||||
| 	int node;               /* Memory node */ | 	int node;               /* Memory node */ | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_XFRM | #ifdef CONFIG_XFRM | ||||||
|  | @ -613,6 +614,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | ||||||
| 	if (pkt_dev->traffic_class) | 	if (pkt_dev->traffic_class) | ||||||
| 		seq_printf(seq, "     traffic_class: 0x%02x\n", pkt_dev->traffic_class); | 		seq_printf(seq, "     traffic_class: 0x%02x\n", pkt_dev->traffic_class); | ||||||
| 
 | 
 | ||||||
|  | 	if (pkt_dev->burst > 1) | ||||||
|  | 		seq_printf(seq, "     burst: %d\n", pkt_dev->burst); | ||||||
|  | 
 | ||||||
| 	if (pkt_dev->node >= 0) | 	if (pkt_dev->node >= 0) | ||||||
| 		seq_printf(seq, "     node: %d\n", pkt_dev->node); | 		seq_printf(seq, "     node: %d\n", pkt_dev->node); | ||||||
| 
 | 
 | ||||||
|  | @ -1124,6 +1128,16 @@ static ssize_t pktgen_if_write(struct file *file, | ||||||
| 			pkt_dev->dst_mac_count); | 			pkt_dev->dst_mac_count); | ||||||
| 		return count; | 		return count; | ||||||
| 	} | 	} | ||||||
|  | 	if (!strcmp(name, "burst")) { | ||||||
|  | 		len = num_arg(&user_buffer[i], 10, &value); | ||||||
|  | 		if (len < 0) | ||||||
|  | 			return len; | ||||||
|  | 
 | ||||||
|  | 		i += len; | ||||||
|  | 		pkt_dev->burst = value < 1 ? 1 : value; | ||||||
|  | 		sprintf(pg_result, "OK: burst=%d", pkt_dev->burst); | ||||||
|  | 		return count; | ||||||
|  | 	} | ||||||
| 	if (!strcmp(name, "node")) { | 	if (!strcmp(name, "node")) { | ||||||
| 		len = num_arg(&user_buffer[i], 10, &value); | 		len = num_arg(&user_buffer[i], 10, &value); | ||||||
| 		if (len < 0) | 		if (len < 0) | ||||||
|  | @ -3297,6 +3311,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev) | ||||||
| 
 | 
 | ||||||
| static void pktgen_xmit(struct pktgen_dev *pkt_dev) | static void pktgen_xmit(struct pktgen_dev *pkt_dev) | ||||||
| { | { | ||||||
|  | 	unsigned int burst = ACCESS_ONCE(pkt_dev->burst); | ||||||
| 	struct net_device *odev = pkt_dev->odev; | 	struct net_device *odev = pkt_dev->odev; | ||||||
| 	struct netdev_queue *txq; | 	struct netdev_queue *txq; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -3347,8 +3362,10 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | ||||||
| 		pkt_dev->last_ok = 0; | 		pkt_dev->last_ok = 0; | ||||||
| 		goto unlock; | 		goto unlock; | ||||||
| 	} | 	} | ||||||
| 	atomic_inc(&(pkt_dev->skb->users)); | 	atomic_add(burst, &pkt_dev->skb->users); | ||||||
| 	ret = netdev_start_xmit(pkt_dev->skb, odev, txq, false); | 
 | ||||||
|  | xmit_more: | ||||||
|  | 	ret = netdev_start_xmit(pkt_dev->skb, odev, txq, --burst > 0); | ||||||
| 
 | 
 | ||||||
| 	switch (ret) { | 	switch (ret) { | ||||||
| 	case NETDEV_TX_OK: | 	case NETDEV_TX_OK: | ||||||
|  | @ -3356,6 +3373,8 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | ||||||
| 		pkt_dev->sofar++; | 		pkt_dev->sofar++; | ||||||
| 		pkt_dev->seq_num++; | 		pkt_dev->seq_num++; | ||||||
| 		pkt_dev->tx_bytes += pkt_dev->last_pkt_size; | 		pkt_dev->tx_bytes += pkt_dev->last_pkt_size; | ||||||
|  | 		if (burst > 0 && !netif_xmit_frozen_or_drv_stopped(txq)) | ||||||
|  | 			goto xmit_more; | ||||||
| 		break; | 		break; | ||||||
| 	case NET_XMIT_DROP: | 	case NET_XMIT_DROP: | ||||||
| 	case NET_XMIT_CN: | 	case NET_XMIT_CN: | ||||||
|  | @ -3374,6 +3393,8 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | ||||||
| 		atomic_dec(&(pkt_dev->skb->users)); | 		atomic_dec(&(pkt_dev->skb->users)); | ||||||
| 		pkt_dev->last_ok = 0; | 		pkt_dev->last_ok = 0; | ||||||
| 	} | 	} | ||||||
|  | 	if (unlikely(burst)) | ||||||
|  | 		atomic_sub(burst, &pkt_dev->skb->users); | ||||||
| unlock: | unlock: | ||||||
| 	HARD_TX_UNLOCK(odev, txq); | 	HARD_TX_UNLOCK(odev, txq); | ||||||
| 
 | 
 | ||||||
|  | @ -3572,6 +3593,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | ||||||
| 	pkt_dev->svlan_p = 0; | 	pkt_dev->svlan_p = 0; | ||||||
| 	pkt_dev->svlan_cfi = 0; | 	pkt_dev->svlan_cfi = 0; | ||||||
| 	pkt_dev->svlan_id = 0xffff; | 	pkt_dev->svlan_id = 0xffff; | ||||||
|  | 	pkt_dev->burst = 1; | ||||||
| 	pkt_dev->node = -1; | 	pkt_dev->node = -1; | ||||||
| 
 | 
 | ||||||
| 	err = pktgen_setup_dev(t->net, pkt_dev, ifname); | 	err = pktgen_setup_dev(t->net, pkt_dev, ifname); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alexei Starovoitov
				Alexei Starovoitov