Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Aug 2017 07:39:53 +0000 (UTC)
From:      Stephen Hurd <shurd@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r448752 - in head/net: . pkt-gen pkt-gen/files
Message-ID:  <201708260739.v7Q7draW033722@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: shurd
Date: Sat Aug 26 07:39:53 2017
New Revision: 448752
URL: https://svnweb.freebsd.org/changeset/ports/448752

Log:
  Add port of pkt-gen, a packet sink/source using the netmap API
  
  Sponsored by:	Limelight Networks
  Differential Revision:	https://reviews.freebsd.org/D12123

Added:
  head/net/pkt-gen/
  head/net/pkt-gen/Makefile   (contents, props changed)
  head/net/pkt-gen/distinfo   (contents, props changed)
  head/net/pkt-gen/files/
  head/net/pkt-gen/files/patch-include_ctrs.h   (contents, props changed)
  head/net/pkt-gen/files/patch-pkt-gen_pkt-gen.c   (contents, props changed)
  head/net/pkt-gen/pkg-descr   (contents, props changed)
Modified:
  head/net/Makefile

Modified: head/net/Makefile
==============================================================================
--- head/net/Makefile	Sat Aug 26 05:40:47 2017	(r448751)
+++ head/net/Makefile	Sat Aug 26 07:39:53 2017	(r448752)
@@ -946,6 +946,7 @@
     SUBDIR += pipsecd
     SUBDIR += pjsip
     SUBDIR += pjsip-extsrtp
+    SUBDIR += pkt-gen
     SUBDIR += pktanon
     SUBDIR += pload
     SUBDIR += plugdaemon

Added: head/net/pkt-gen/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/pkt-gen/Makefile	Sat Aug 26 07:39:53 2017	(r448752)
@@ -0,0 +1,32 @@
+# $FreeBSD$
+
+PORTNAME=	pkt-gen
+PORTVERSION=	g2017.08.06
+CATEGORIES=	net
+
+MAINTAINER=	shurd@freebsd.org
+COMMENT=	Packet sink/source using the netmap API
+
+LICENSE=	BSD2CLAUSE
+
+USES=		gmake
+USE_GITHUB=	yes
+GH_ACCOUNT=	luigirizzo
+GH_PROJECT=	netmap
+GH_TAGNAME=	3c3ab5faa2ab9c89db09cd8339d0e96a1a78c41a
+MAKEFILE=	GNUmakefile
+WRKSRC_SUBDIR=	apps/pkt-gen
+PATCH_WRKSRC=	${WRKSRC}/..
+
+OPTIONS_DEFINE=	PCAP
+PCAP_DESC=	Support loading packets from pcap file
+OPTIONS_DEFAULT=PCAP
+PCAP_MAKE_ARGS=	WITH_PCAP=1
+
+PLIST_FILES=	bin/pkt-gen
+
+do-install:
+	${INSTALL_PROGRAM} ${WRKSRC}/pkt-gen \
+		${STAGEDIR}${PREFIX}/bin
+
+.include <bsd.port.mk>

Added: head/net/pkt-gen/distinfo
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/pkt-gen/distinfo	Sat Aug 26 07:39:53 2017	(r448752)
@@ -0,0 +1,3 @@
+TIMESTAMP = 1503651090
+SHA256 (luigirizzo-netmap-g2017.08.06-3c3ab5faa2ab9c89db09cd8339d0e96a1a78c41a_GH0.tar.gz) = 755f0b7d195cfdd7148591ef01ae4da569cae3e323ffded74dfbaa571dc267f3
+SIZE (luigirizzo-netmap-g2017.08.06-3c3ab5faa2ab9c89db09cd8339d0e96a1a78c41a_GH0.tar.gz) = 544000

Added: head/net/pkt-gen/files/patch-include_ctrs.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/pkt-gen/files/patch-include_ctrs.h	Sat Aug 26 07:39:53 2017	(r448752)
@@ -0,0 +1,36 @@
+--- include/ctrs.h.orig	2017-08-06 18:26:36 UTC
++++ include/ctrs.h
+@@ -16,21 +16,27 @@ struct my_ctrs {
+  * Caller has to make sure that the buffer is large enough.
+  */
+ static const char *
+-norm2(char *buf, double val, char *fmt)
++norm2(char *buf, double val, char *fmt, int normalize)
+ {
+ 	char *units[] = { "", "K", "M", "G", "T" };
+ 	u_int i;
+-
+-	for (i = 0; val >=1000 && i < sizeof(units)/sizeof(char *) - 1; i++)
+-		val /= 1000;
++	if (normalize)
++		for (i = 0; val >=1000 && i < sizeof(units)/sizeof(char *) - 1; i++)
++			val /= 1000;
++	else
++		i=0;
+ 	sprintf(buf, fmt, val, units[i]);
+ 	return buf;
+ }
+ 
+ static __inline const char *
+-norm(char *buf, double val)
++norm(char *buf, double val, int normalize)
+ {
+-	return norm2(buf, val, "%.3f %s");
++	
++	if (normalize)
++		return norm2(buf, val, "%.3f %s", normalize);
++	else
++		return norm2(buf, val, "%.0f %s", normalize);
+ }
+ 
+ static __inline int

Added: head/net/pkt-gen/files/patch-pkt-gen_pkt-gen.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/pkt-gen/files/patch-pkt-gen_pkt-gen.c	Sat Aug 26 07:39:53 2017	(r448752)
@@ -0,0 +1,562 @@
+--- pkt-gen/pkt-gen.c.orig	2017-08-06 18:26:36 UTC
++++ pkt-gen/pkt-gen.c
+@@ -186,6 +186,7 @@ const char *indirect_payload="netmap pkt
+ 	"http://info.iet.unipi.it/~luigi/netmap/ ";
+ 
+ int verbose = 0;
++int normalize = 1;
+ 
+ #define VIRT_HDR_1	10	/* length of a base vnet-hdr */
+ #define VIRT_HDR_2	12	/* length of the extenede vnet-hdr */
+@@ -204,12 +205,12 @@ struct pkt {
+ 			struct ip ip;
+ 			struct udphdr udp;
+ 			uint8_t body[MAX_BODYSIZE];	/* hardwired */
+-		} ipv4;
++		} __attribute__((__packed__)) ipv4;
+ 		struct {
+ 			struct ip6_hdr ip;
+ 			struct udphdr udp;
+ 			uint8_t body[MAX_BODYSIZE];	/* hardwired */
+-		} ipv6;
++		} __attribute__((__packed__)) ipv6;
+ 	};
+ } __attribute__((__packed__));
+ 
+@@ -752,39 +753,39 @@ dump_payload(const char *_p, int len, st
+ static void
+ update_ip(struct pkt *pkt, struct glob_arg *g)
+ {
+-	struct ip *ip;
+-	struct udphdr *udp;
++	struct ip ip;
++	struct udphdr udp;
+ 	uint32_t oaddr, naddr;
+ 	uint16_t oport, nport;
+ 	uint16_t ip_sum, udp_sum;
+ 
+-	ip = &pkt->ipv4.ip;
+-	udp = &pkt->ipv4.udp;
++	memcpy(&ip, &pkt->ipv4.ip, sizeof(ip));
++	memcpy(&udp, &pkt->ipv4.udp, sizeof(udp));
+ 	do {
+ 		ip_sum = udp_sum = 0;
+-		naddr = oaddr = ntohl(ip->ip_src.s_addr);
+-		nport = oport = ntohs(udp->uh_sport);
++		naddr = oaddr = ntohl(ip.ip_src.s_addr);
++		nport = oport = ntohs(udp.uh_sport);
+ 		if (g->options & OPT_RANDOM_SRC) {
+-			ip->ip_src.s_addr = random();
+-			udp->uh_sport = random();
+-			naddr = ntohl(ip->ip_src.s_addr);
+-			nport = ntohs(udp->uh_sport);
++			ip.ip_src.s_addr = random();
++			udp.uh_sport = random();
++			naddr = ntohl(ip.ip_src.s_addr);
++			nport = ntohs(udp.uh_sport);
+ 			break;
+ 		}
+ 		if (oport < g->src_ip.port1) {
+ 			nport = oport + 1;
+-			udp->uh_sport = htons(nport);
++			udp.uh_sport = htons(nport);
+ 			break;
+ 		}
+ 		nport = g->src_ip.port0;
+-		udp->uh_sport = htons(nport);
++		udp.uh_sport = htons(nport);
+ 		if (oaddr < g->src_ip.ipv4.end) {
+ 			naddr = oaddr + 1;
+-			ip->ip_src.s_addr = htonl(naddr);
++			ip.ip_src.s_addr = htonl(naddr);
+ 			break;
+ 		}
+ 		naddr = g->src_ip.ipv4.start;
+-		ip->ip_src.s_addr = htonl(naddr);
++		ip.ip_src.s_addr = htonl(naddr);
+ 	} while (0);
+ 	/* update checksums if needed */
+ 	if (oaddr != naddr) {
+@@ -798,29 +799,29 @@ update_ip(struct pkt *pkt, struct glob_a
+ 		udp_sum = cksum_add(udp_sum, nport);
+ 	}
+ 	do {
+-		naddr = oaddr = ntohl(ip->ip_dst.s_addr);
+-		nport = oport = ntohs(udp->uh_dport);
++		naddr = oaddr = ntohl(ip.ip_dst.s_addr);
++		nport = oport = ntohs(udp.uh_dport);
+ 		if (g->options & OPT_RANDOM_DST) {
+-			ip->ip_dst.s_addr = random();
+-			udp->uh_dport = random();
+-			naddr = ntohl(ip->ip_dst.s_addr);
+-			nport = ntohs(udp->uh_dport);
++			ip.ip_dst.s_addr = random();
++			udp.uh_dport = random();
++			naddr = ntohl(ip.ip_dst.s_addr);
++			nport = ntohs(udp.uh_dport);
+ 			break;
+ 		}
+ 		if (oport < g->dst_ip.port1) {
+ 			nport = oport + 1;
+-			udp->uh_dport = htons(nport);
++			udp.uh_dport = htons(nport);
+ 			break;
+ 		}
+ 		nport = g->dst_ip.port0;
+-		udp->uh_dport = htons(nport);
++		udp.uh_dport = htons(nport);
+ 		if (oaddr < g->dst_ip.ipv4.end) {
+ 			naddr = oaddr + 1;
+-			ip->ip_dst.s_addr = htonl(naddr);
++			ip.ip_dst.s_addr = htonl(naddr);
+ 			break;
+ 		}
+ 		naddr = g->dst_ip.ipv4.start;
+-		ip->ip_dst.s_addr = htonl(naddr);
++		ip.ip_dst.s_addr = htonl(naddr);
+ 	} while (0);
+ 	/* update checksums */
+ 	if (oaddr != naddr) {
+@@ -834,11 +835,13 @@ update_ip(struct pkt *pkt, struct glob_a
+ 		udp_sum = cksum_add(udp_sum, nport);
+ 	}
+ 	if (udp_sum != 0)
+-		udp->uh_sum = ~cksum_add(~udp->uh_sum, htons(udp_sum));
++		udp.uh_sum = ~cksum_add(~udp.uh_sum, htons(udp_sum));
+ 	if (ip_sum != 0) {
+-		ip->ip_sum = ~cksum_add(~ip->ip_sum, htons(ip_sum));
+-		udp->uh_sum = ~cksum_add(~udp->uh_sum, htons(ip_sum));
++		ip.ip_sum = ~cksum_add(~ip.ip_sum, htons(ip_sum));
++		udp.uh_sum = ~cksum_add(~udp.uh_sum, htons(ip_sum));
+ 	}
++	memcpy(&pkt->ipv4.ip, &ip, sizeof(ip));
++	memcpy(&pkt->ipv4.udp, &udp, sizeof(udp));
+ }
+ 
+ #ifndef s6_addr16
+@@ -847,41 +850,41 @@ update_ip(struct pkt *pkt, struct glob_a
+ static void
+ update_ip6(struct pkt *pkt, struct glob_arg *g)
+ {
+-	struct ip6_hdr *ip6;
+-	struct udphdr *udp;
++	struct ip6_hdr ip6;
++	struct udphdr udp;
+ 	uint16_t udp_sum;
+ 	uint16_t oaddr, naddr;
+ 	uint16_t oport, nport;
+ 	uint8_t group;
+ 
+-	ip6 = &pkt->ipv6.ip;
+-	udp = &pkt->ipv6.udp;
++	memcpy(&ip6, &pkt->ipv6.ip, sizeof(ip6));
++	memcpy(&udp, &pkt->ipv6.udp, sizeof(udp));
+ 	do {
+ 		udp_sum = 0;
+ 		group = g->src_ip.ipv6.sgroup;
+-		naddr = oaddr = ntohs(ip6->ip6_src.s6_addr16[group]);
+-		nport = oport = ntohs(udp->uh_sport);
++		naddr = oaddr = ntohs(ip6.ip6_src.s6_addr16[group]);
++		nport = oport = ntohs(udp.uh_sport);
+ 		if (g->options & OPT_RANDOM_SRC) {
+-			ip6->ip6_src.s6_addr16[group] = random();
+-			udp->uh_sport = random();
+-			naddr = ntohs(ip6->ip6_src.s6_addr16[group]);
+-			nport = ntohs(udp->uh_sport);
++			ip6.ip6_src.s6_addr16[group] = random();
++			udp.uh_sport = random();
++			naddr = ntohs(ip6.ip6_src.s6_addr16[group]);
++			nport = ntohs(udp.uh_sport);
+ 			break;
+ 		}
+ 		if (oport < g->src_ip.port1) {
+ 			nport = oport + 1;
+-			udp->uh_sport = htons(nport);
++			udp.uh_sport = htons(nport);
+ 			break;
+ 		}
+ 		nport = g->src_ip.port0;
+-		udp->uh_sport = htons(nport);
++		udp.uh_sport = htons(nport);
+ 		if (oaddr < ntohs(g->src_ip.ipv6.end.s6_addr16[group])) {
+ 			naddr = oaddr + 1;
+-			ip6->ip6_src.s6_addr16[group] = htons(naddr);
++			ip6.ip6_src.s6_addr16[group] = htons(naddr);
+ 			break;
+ 		}
+ 		naddr = ntohs(g->src_ip.ipv6.start.s6_addr16[group]);
+-		ip6->ip6_src.s6_addr16[group] = htons(naddr);
++		ip6.ip6_src.s6_addr16[group] = htons(naddr);
+ 	} while (0);
+ 	/* update checksums if needed */
+ 	if (oaddr != naddr)
+@@ -891,29 +894,29 @@ update_ip6(struct pkt *pkt, struct glob_
+ 		    cksum_add(~oport, nport));
+ 	do {
+ 		group = g->dst_ip.ipv6.egroup;
+-		naddr = oaddr = ntohs(ip6->ip6_dst.s6_addr16[group]);
+-		nport = oport = ntohs(udp->uh_dport);
++		naddr = oaddr = ntohs(ip6.ip6_dst.s6_addr16[group]);
++		nport = oport = ntohs(udp.uh_dport);
+ 		if (g->options & OPT_RANDOM_DST) {
+-			ip6->ip6_dst.s6_addr16[group] = random();
+-			udp->uh_dport = random();
+-			naddr = ntohs(ip6->ip6_dst.s6_addr16[group]);
+-			nport = ntohs(udp->uh_dport);
++			ip6.ip6_dst.s6_addr16[group] = random();
++			udp.uh_dport = random();
++			naddr = ntohs(ip6.ip6_dst.s6_addr16[group]);
++			nport = ntohs(udp.uh_dport);
+ 			break;
+ 		}
+ 		if (oport < g->dst_ip.port1) {
+ 			nport = oport + 1;
+-			udp->uh_dport = htons(nport);
++			udp.uh_dport = htons(nport);
+ 			break;
+ 		}
+ 		nport = g->dst_ip.port0;
+-		udp->uh_dport = htons(nport);
++		udp.uh_dport = htons(nport);
+ 		if (oaddr < ntohs(g->dst_ip.ipv6.end.s6_addr16[group])) {
+ 			naddr = oaddr + 1;
+-			ip6->ip6_dst.s6_addr16[group] = htons(naddr);
++			ip6.ip6_dst.s6_addr16[group] = htons(naddr);
+ 			break;
+ 		}
+ 		naddr = ntohs(g->dst_ip.ipv6.start.s6_addr16[group]);
+-		ip6->ip6_dst.s6_addr16[group] = htons(naddr);
++		ip6.ip6_dst.s6_addr16[group] = htons(naddr);
+ 	} while (0);
+ 	/* update checksums */
+ 	if (oaddr != naddr)
+@@ -923,7 +926,9 @@ update_ip6(struct pkt *pkt, struct glob_
+ 		udp_sum = cksum_add(udp_sum,
+ 		    cksum_add(~oport, nport));
+ 	if (udp_sum != 0)
+-		udp->uh_sum = ~cksum_add(~udp->uh_sum, udp_sum);
++		udp.uh_sum = ~cksum_add(~udp.uh_sum, udp_sum);
++	memcpy(&pkt->ipv6.ip, &ip6, sizeof(ip6));
++	memcpy(&pkt->ipv6.udp, &udp, sizeof(udp));
+ }
+ 
+ static void
+@@ -944,9 +949,10 @@ initialize_packet(struct targ *targ)
+ {
+ 	struct pkt *pkt = &targ->pkt;
+ 	struct ether_header *eh;
+-	struct ip6_hdr *ip6;
+-	struct ip *ip;
+-	struct udphdr *udp;
++	struct ip6_hdr ip6;
++	struct ip ip;
++	struct udphdr udp;
++	void *udp_ptr;
+ 	uint16_t paylen;
+ 	uint32_t csum;
+ 	const char *payload = targ->g->options & OPT_INDIRECT ?
+@@ -978,7 +984,7 @@ initialize_packet(struct targ *targ)
+ #endif
+ 
+ 	paylen = targ->g->pkt_size - sizeof(*eh) -
+-	    (targ->g->af == AF_INET ? sizeof(*ip): sizeof(*ip6));
++	    (targ->g->af == AF_INET ? sizeof(ip): sizeof(ip6));
+ 
+ 	/* create a nice NUL-terminated string */
+ 	for (i = 0; i < paylen; i += l0) {
+@@ -995,56 +1001,61 @@ initialize_packet(struct targ *targ)
+ 
+ 	if (targ->g->af == AF_INET) {
+ 		eh->ether_type = htons(ETHERTYPE_IP);
+-		ip = &pkt->ipv4.ip;
+-		udp = &pkt->ipv4.udp;
+-		ip->ip_v = IPVERSION;
+-		ip->ip_hl = sizeof(*ip) >> 2;
+-		ip->ip_id = 0;
+-		ip->ip_tos = IPTOS_LOWDELAY;
+-		ip->ip_len = htons(targ->g->pkt_size - sizeof(*eh));
+-		ip->ip_id = 0;
+-		ip->ip_off = htons(IP_DF); /* Don't fragment */
+-		ip->ip_ttl = IPDEFTTL;
+-		ip->ip_p = IPPROTO_UDP;
+-		ip->ip_dst.s_addr = htonl(targ->g->dst_ip.ipv4.start);
+-		ip->ip_src.s_addr = htonl(targ->g->src_ip.ipv4.start);
+-		ip->ip_sum = wrapsum(checksum(ip, sizeof(*ip), 0));
++		memcpy(&ip, &pkt->ipv4.ip, sizeof(ip));
++		udp_ptr = &pkt->ipv4.udp;
++		ip.ip_v = IPVERSION;
++		ip.ip_hl = sizeof(ip) >> 2;
++		ip.ip_id = 0;
++		ip.ip_tos = IPTOS_LOWDELAY;
++		ip.ip_len = htons(targ->g->pkt_size - sizeof(*eh));
++		ip.ip_id = 0;
++		ip.ip_off = htons(IP_DF); /* Don't fragment */
++		ip.ip_ttl = IPDEFTTL;
++		ip.ip_p = IPPROTO_UDP;
++		ip.ip_dst.s_addr = htonl(targ->g->dst_ip.ipv4.start);
++		ip.ip_src.s_addr = htonl(targ->g->src_ip.ipv4.start);
++		ip.ip_sum = wrapsum(checksum(&ip, sizeof(ip), 0));
++		memcpy(&pkt->ipv4.ip, &ip, sizeof(ip));
+ 	} else {
+ 		eh->ether_type = htons(ETHERTYPE_IPV6);
+-		ip6 = &pkt->ipv6.ip;
+-		udp = &pkt->ipv6.udp;
+-		ip6->ip6_flow = 0;
+-		ip6->ip6_plen = htons(paylen);
+-		ip6->ip6_vfc = IPV6_VERSION;
+-		ip6->ip6_nxt = IPPROTO_UDP;
+-		ip6->ip6_hlim = IPV6_DEFHLIM;
+-		ip6->ip6_src = targ->g->src_ip.ipv6.start;
+-		ip6->ip6_dst = targ->g->dst_ip.ipv6.start;
++		memcpy(&ip6, &pkt->ipv4.ip, sizeof(ip6));
++		udp_ptr = &pkt->ipv6.udp;
++		ip6.ip6_flow = 0;
++		ip6.ip6_plen = htons(paylen);
++		ip6.ip6_vfc = IPV6_VERSION;
++		ip6.ip6_nxt = IPPROTO_UDP;
++		ip6.ip6_hlim = IPV6_DEFHLIM;
++		ip6.ip6_src = targ->g->src_ip.ipv6.start;
++		ip6.ip6_dst = targ->g->dst_ip.ipv6.start;
+ 	}
++	memcpy(&udp, udp_ptr, sizeof(udp));
+ 
+-	udp->uh_sport = htons(targ->g->src_ip.port0);
+-	udp->uh_dport = htons(targ->g->dst_ip.port0);
+-	udp->uh_ulen = htons(paylen);
++	udp.uh_sport = htons(targ->g->src_ip.port0);
++	udp.uh_dport = htons(targ->g->dst_ip.port0);
++	udp.uh_ulen = htons(paylen);
+ 	if (targ->g->af == AF_INET) {
+ 		/* Magic: taken from sbin/dhclient/packet.c */
+-		udp->uh_sum = wrapsum(
+-		    checksum(udp, sizeof(*udp),	/* udp header */
++		udp.uh_sum = wrapsum(
++		    checksum(&udp, sizeof(udp),	/* udp header */
+                     checksum(pkt->ipv4.body,	/* udp payload */
+-		    paylen - sizeof(*udp),
++		    paylen - sizeof(udp),
+ 		    checksum(&pkt->ipv4.ip.ip_src, /* pseudo header */
+ 			2 * sizeof(pkt->ipv4.ip.ip_src),
+-			IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)))));
++			IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen)))));
++		memcpy(&pkt->ipv4.ip, &ip, sizeof(ip));
+ 	} else {
+ 		/* Save part of pseudo header checksum into csum */
+ 		csum = IPPROTO_UDP << 24;
+ 		csum = checksum(&csum, sizeof(csum), paylen);
+-		udp->uh_sum = wrapsum(
+-		    checksum(udp, sizeof(*udp),	/* udp header */
++		udp.uh_sum = wrapsum(
++		    checksum(udp_ptr, sizeof(udp),	/* udp header */
+ 		    checksum(pkt->ipv6.body,	/* udp payload */
+-		    paylen - sizeof(*udp),
++		    paylen - sizeof(udp),
+ 		    checksum(&pkt->ipv6.ip.ip6_src, /* pseudo header */
+ 			2 * sizeof(pkt->ipv6.ip.ip6_src), csum))));
++		memcpy(&pkt->ipv6.ip, &ip6, sizeof(ip6));
+ 	}
++	memcpy(udp_ptr, &udp, sizeof(udp));
+ 
+ 	bzero(&pkt->vh, sizeof(pkt->vh));
+ 	// dump_payload((void *)pkt, targ->g->pkt_size, NULL, 0);
+@@ -1864,6 +1875,7 @@ txseq_body(void *data)
+ 		unsigned int space;
+ 		unsigned int head;
+ 		int fcnt;
++		uint16_t sum;
+ 
+ 		if (!rate_limit) {
+ 			budget = targ->g->burst;
+@@ -1910,19 +1922,19 @@ txseq_body(void *data)
+ 				sent < limit; sent++, sequence++) {
+ 			struct netmap_slot *slot = &ring->slot[head];
+ 			char *p = NETMAP_BUF(ring, slot->buf_idx);
+-			uint16_t *w = (uint16_t *)PKT(pkt, body, targ->g->af), t,
+-				 *sum = (uint16_t *)(targ->g->af == AF_INET ?
+-						 &pkt->ipv4.udp.uh_sum : &pkt->ipv6.udp.uh_sum);
++			uint16_t *w = (uint16_t *)PKT(pkt, body, targ->g->af), t;
++
++			memcpy(&sum, targ->g->af == AF_INET ? &pkt->ipv4.udp.uh_sum : &pkt->ipv6.udp.uh_sum, sizeof(sum));
+ 
+ 			slot->flags = 0;
+ 			t = *w;
+ 			PKT(pkt, body, targ->g->af)[0] = sequence >> 24;
+ 			PKT(pkt, body, targ->g->af)[1] = (sequence >> 16) & 0xff;
+-			*sum = ~cksum_add(~*sum, cksum_add(~t, *w));
++			sum = ~cksum_add(~sum, cksum_add(~t, *w));
+ 			t = *++w;
+ 			PKT(pkt, body, targ->g->af)[2] = (sequence >> 8) & 0xff;
+ 			PKT(pkt, body, targ->g->af)[3] = sequence & 0xff;
+-			*sum = ~cksum_add(~*sum, cksum_add(~t, *w));
++			sum = ~cksum_add(~sum, cksum_add(~t, *w));
+ 			nm_pkt_copy(frame, p, size);
+ 			if (fcnt == frags) {
+ 				update_addresses(pkt, targ->g);
+@@ -1952,6 +1964,7 @@ txseq_body(void *data)
+ 				budget--;
+ 			}
+ 		}
++		memcpy(targ->g->af == AF_INET ? &pkt->ipv4.udp.uh_sum : &pkt->ipv6.udp.uh_sum, &sum, sizeof(sum));
+ 
+ 		ring->cur = ring->head = head;
+ 
+@@ -2209,7 +2222,7 @@ tx_output(struct my_ctrs *cur, double de
+ 	abs = cur->pkts / (double)(cur->events);
+ 
+ 	printf("Speed: %spps Bandwidth: %sbps (raw %sbps). Average batch: %.2f pkts\n",
+-		norm(b1, pps), norm(b2, bw), norm(b3, raw_bw), abs);
++		norm(b1, pps, normalize), norm(b2, bw, normalize), norm(b3, raw_bw, normalize), abs);
+ }
+ 
+ static void
+@@ -2219,38 +2232,72 @@ usage(void)
+ 	fprintf(stderr,
+ 		"Usage:\n"
+ 		"%s arguments\n"
+-		"\t-i interface		interface name\n"
+-		"\t-f function		tx rx ping pong txseq rxseq\n"
+-		"\t-n count		number of iterations (can be 0)\n"
+-		"\t-t pkts_to_send	also forces tx mode\n"
+-		"\t-r pkts_to_receive	also forces rx mode\n"
+-		"\t-l pkt_size		in bytes excluding CRC\n"
+-		"\t                     (if passed a second time, use random sizes\n"
+-		"\t                      bigger than the second one and lower than\n"
+-		"\t                      the first one)\n"
+-		"\t-d dst_ip[:port[-dst_ip:port]]   single or range\n"
+-		"\t-s src_ip[:port[-src_ip:port]]   single or range\n"
+-		"\t-D dst-mac\n"
+-		"\t-S src-mac\n"
+-		"\t-a cpu_id		use setaffinity\n"
+-		"\t-b burst size		testing, mostly\n"
+-		"\t-c cores		cores to use\n"
+-		"\t-p threads		processes/threads to use\n"
+-		"\t-T report_ms		milliseconds between reports\n"
+-		"\t-w wait_for_link_time	in seconds\n"
+-		"\t-R rate		in packets per second\n"
+-		"\t-X			dump payload\n"
+-		"\t-H len		add empty virtio-net-header with size 'len'\n"
+-		"\t-E pipes		allocate extra space for a number of pipes\n"
+-		"\t-r			do not touch the buffers (send rubbish)\n"
+-	        "\t-P file		load packet from pcap file\n"
+-		"\t-z			use random IPv4 src address/port\n"
+-		"\t-Z			use random IPv4 dst address/port\n"
+-		"\t-F num_frags		send multi-slot packets\n"
+-		"\t-A			activate pps stats on receiver\n"
+-		"",
++		     "\t-i interface		interface name\n"
++		     "\t-f function		tx rx ping pong txseq rxseq\n"
++		     "\t-n count		number of iterations (can be 0)\n"
++#ifdef notyet
++		     "\t-t pkts_to_send		also forces tx mode\n"
++		     "\t-r pkts_to_receive	also forces rx mode\n"
++#endif
++		     "\t-l pkt_size		in bytes excluding CRC\n"
++		     "\t			(if passed a second time, use random sizes\n"
++		     "\t			 bigger than the second one and lower than\n"
++		     "\t			 the first one)\n"
++		     "\t-d dst_ip[:port[-dst_ip:port]]   single or range\n"
++		     "\t-s src_ip[:port[-src_ip:port]]   single or range\n"
++		     "\t-D dst-mac\n"
++		     "\t-S src-mac\n"
++		     "\t-a cpu_id		use setaffinity\n"
++		     "\t-b burst size		testing, mostly\n"
++		     "\t-c cores		cores to use\n"
++		     "\t-p threads		processes/threads to use\n"
++		     "\t-T report_ms		milliseconds between reports\n"
++		     "\t-w wait_for_link_time	in seconds\n"
++		     "\t-R rate			in packets per second\n"
++		     "\t-X			dump payload\n"
++		     "\t-H len			add empty virtio-net-header with size 'len'\n"
++		     "\t-E pipes		allocate extra space for a number of pipes\n"
++		     "\t-r			do not touch the buffers (send rubbish)\n"
++	             "\t-P file			load packet from pcap file\n"
++		     "\t-z			use random IPv4 src address/port\n"
++		     "\t-Z			use random IPv4 dst address/port\n"
++		     "\t-F num_frags		send multi-slot packets\n"
++		     "\t-A			activate pps stats on receiver\n"
++		     "\t-4			IPv4\n"
++		     "\t-6			IPv6\n"
++		     "\t-N			don't normalize units (Kbps/Mbps/etc)\n"
++		     "\t-I			use indirect buffers, tx only\n"
++		     "\t-o options		data generation options (parsed using atoi)\n"
++		     "\t			OPT_PREFETCH	1\n"
++		     "\t			OPT_ACCESS	2\n"
++		     "\t			OPT_COPY	4\n"
++		     "\t			OPT_MEMCPY	8\n"
++		     "\t			OPT_TS		16 (add a timestamp)\n"
++		     "\t			OPT_INDIRECT	32 (use indirect buffers)\n"
++		     "\t			OPT_DUMP	64 (dump rx/tx traffic)\n"
++		     "\t			OPT_RUBBISH	256\n"
++		     "\t			    (send wathever the buffers contain)\n"
++		     "\t			OPT_RANDOM_SRC  512\n"
++		     "\t			OPT_RANDOM_DST  1024\n"
++		     "\t			OPT_PPS_STATS   2048\n"
++		     "\t-W			exit RX with no traffic\n"
++		     "\t-v			verbose (more v = more verbose)\n"
++		     "\t-C vale-config		specify a vale config\n"
++#ifdef notyet
++		     "\t			The configuration may consist of 0 to 4\n"
++		     "\t			numbers separated by commas:\n"
++		     "\t			#tx-slots,#rx-slots,#tx-rings,#rx-rings.\n"
++		     "\t			Missing numbers or zeroes stand for default\n"
++		     "\t			values. As an additional convenience, if\n"
++		     "\t			exactly one number is specified, then this\n"
++		     "\t			is assigned to both #tx-slots and #rx-slots.\n"
++		     "\t			If there is no 4th number, then the 3rd is\n"
++		     "\t			assigned to both #tx-rings and #rx-rings.\n"
++#endif
++		     "\t-e extra-bufs		extra_bufs - goes in nr_arg3\n"
++		     "\t-m			ignored\n"
++		     "",
+ 		cmd);
+-
+ 	exit(0);
+ }
+ 
+@@ -2405,13 +2452,13 @@ main_thread(struct glob_arg *g)
+ 			ppsdev = sqrt(ppsdev);
+ 
+ 			snprintf(b4, sizeof(b4), "[avg/std %s/%s pps]",
+-				 norm(b1, ppsavg), norm(b2, ppsdev));
++				 norm(b1, ppsavg, normalize), norm(b2, ppsdev, normalize));
+ 		}
+ 
+ 		D("%spps %s(%spkts %sbps in %llu usec) %.2f avg_batch %d min_space",
+-			norm(b1, pps), b4,
+-			norm(b2, (double)x.pkts),
+-			norm(b3, (double)x.bytes*8),
++			norm(b1, pps, normalize), b4,
++			norm(b2, (double)x.pkts, normalize),
++			norm(b3, (double)x.bytes*8, normalize),
+ 			(unsigned long long)usec,
+ 			abs, (int)cur.min_space);
+ 		prev = cur;
+@@ -2589,7 +2636,7 @@ main(int arc, char **argv)
+ 	g.virt_header = 0;
+ 	g.wait_link = 2;
+ 
+-	while ((ch = getopt(arc, argv, "46a:f:F:n:i:Il:d:s:D:S:b:c:o:p:"
++	while ((ch = getopt(arc, argv, "46a:f:F:Nn:i:Il:d:s:D:S:b:c:o:p:"
+ 	    "T:w:WvR:XC:H:e:E:m:rP:zZA")) != -1) {
+ 
+ 		switch(ch) {
+@@ -2606,6 +2653,10 @@ main(int arc, char **argv)
+ 			g.af = AF_INET6;
+ 			break;
+ 
++		case 'N':
++			normalize = 0;
++			break;
++
+ 		case 'n':
+ 			g.npackets = strtoull(optarg, NULL, 10);
+ 			break;
+@@ -2633,7 +2684,7 @@ main(int arc, char **argv)
+ 			break;
+ 
+ 		case 'o':	/* data generation options */
+-			g.options = atoi(optarg);
++			g.options |= atoi(optarg);
+ 			break;
+ 
+ 		case 'a':       /* force affinity */

Added: head/net/pkt-gen/pkg-descr
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/pkt-gen/pkg-descr	Sat Aug 26 07:39:53 2017	(r448752)
@@ -0,0 +1,5 @@
+Packet sink/source using the netmap API useful for perforamce testing
+networks.  This is the upstream version of the program by the same name
+that lives in /usr/src/tools/tools/netmap, maintained by Luigi Rizzo.
+
+WWW: https://github.com/luigirizzo/netmap



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708260739.v7Q7draW033722>