[Midnightbsd-cvs] src [11936] trunk/tools/tools/netrate/netreceive: update
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jul 21 15:59:02 EDT 2018
Revision: 11936
http://svnweb.midnightbsd.org/src/?rev=11936
Author: laffer1
Date: 2018-07-21 15:59:01 -0400 (Sat, 21 Jul 2018)
Log Message:
-----------
update
Modified Paths:
--------------
trunk/tools/tools/netrate/netreceive/Makefile
trunk/tools/tools/netrate/netreceive/netreceive.c
Modified: trunk/tools/tools/netrate/netreceive/Makefile
===================================================================
--- trunk/tools/tools/netrate/netreceive/Makefile 2018-07-21 17:04:20 UTC (rev 11935)
+++ trunk/tools/tools/netrate/netreceive/Makefile 2018-07-21 19:59:01 UTC (rev 11936)
@@ -1,8 +1,12 @@
+# $MidnightBSD$
#
-# $FreeBSD: src/tools/tools/netrate/netreceive/Makefile,v 1.3 2004/12/21 08:47:28 ru Exp $
+# $FreeBSD: stable/10/tools/tools/netrate/netreceive/Makefile 276486 2014-12-31 23:25:37Z ngie $
#
PROG= netreceive
-NO_MAN=
+MAN=
+LDFLAGS += -lpthread
+WARNS?= 3
+
.include <bsd.prog.mk>
Modified: trunk/tools/tools/netrate/netreceive/netreceive.c
===================================================================
--- trunk/tools/tools/netrate/netreceive/netreceive.c 2018-07-21 17:04:20 UTC (rev 11935)
+++ trunk/tools/tools/netrate/netreceive/netreceive.c 2018-07-21 19:59:01 UTC (rev 11936)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2004 Robert N. M. Watson
* All rights reserved.
@@ -23,14 +24,16 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/tools/tools/netrate/netreceive/netreceive.c,v 1.2 2004/09/21 03:10:28 rwatson Exp $
+ * $FreeBSD: stable/10/tools/tools/netrate/netreceive/netreceive.c 244672 2012-12-25 07:29:25Z luigi $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/poll.h>
#include <netinet/in.h>
+#include <netdb.h> /* getaddrinfo */
#include <arpa/inet.h>
@@ -37,35 +40,186 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h> /* close */
+#define MAXSOCK 20
+
+#include <pthread.h>
+#include <fcntl.h>
+#include <time.h> /* clock_getres() */
+
+static int round_to(int n, int l)
+{
+ return ((n + l - 1)/l)*l;
+}
+
+/*
+ * Each socket uses multiple threads so the receiver is
+ * more efficient. A collector thread runs the stats.
+ */
+struct td_desc {
+ pthread_t td_id;
+ uint64_t count; /* rx counter */
+ uint64_t byte_count; /* rx byte counter */
+ int fd;
+ char *buf;
+ int buflen;
+};
+
static void
usage(void)
{
- fprintf(stderr, "netreceive [port]\n");
+ fprintf(stderr, "netreceive port [nthreads]\n");
exit(-1);
}
+static __inline void
+timespec_add(struct timespec *tsa, struct timespec *tsb)
+{
+
+ tsa->tv_sec += tsb->tv_sec;
+ tsa->tv_nsec += tsb->tv_nsec;
+ if (tsa->tv_nsec >= 1000000000) {
+ tsa->tv_sec++;
+ tsa->tv_nsec -= 1000000000;
+ }
+}
+
+static __inline void
+timespec_sub(struct timespec *tsa, struct timespec *tsb)
+{
+
+ tsa->tv_sec -= tsb->tv_sec;
+ tsa->tv_nsec -= tsb->tv_nsec;
+ if (tsa->tv_nsec < 0) {
+ tsa->tv_sec--;
+ tsa->tv_nsec += 1000000000;
+ }
+}
+
+static void *
+rx_body(void *data)
+{
+ struct td_desc *t = data;
+ struct pollfd fds;
+ int y;
+
+ fds.fd = t->fd;
+ fds.events = POLLIN;
+
+ for (;;) {
+ if (poll(&fds, 1, -1) < 0)
+ perror("poll on thread");
+ if (!(fds.revents & POLLIN))
+ continue;
+ for (;;) {
+ y = recv(t->fd, t->buf, t->buflen, MSG_DONTWAIT);
+ if (y < 0)
+ break;
+ t->count++;
+ t->byte_count += y;
+ }
+ }
+ return NULL;
+}
+
+static struct td_desc **
+make_threads(int *s, int nsock, int nthreads)
+{
+ int i, si, nt = nsock * nthreads;
+ int lb = round_to(nt * sizeof (struct td_desc *), 64);
+ int td_len = round_to(sizeof(struct td_desc), 64); // cache align
+ char *m = calloc(1, lb + td_len * nt);
+ struct td_desc **tp;
+
+ printf("td len %d -> %d\n", (int)sizeof(struct td_desc) , td_len);
+ /* pointers plus the structs */
+ if (m == NULL) {
+ perror("no room for pointers!");
+ exit(1);
+ }
+ tp = (struct td_desc **)m;
+ m += lb; /* skip the pointers */
+ for (si = i = 0; i < nt; i++, m += td_len) {
+ tp[i] = (struct td_desc *)m;
+ tp[i]->fd = s[si];
+ tp[i]->buflen = 65536;
+ tp[i]->buf = calloc(1, tp[i]->buflen);
+ if (++si == nsock)
+ si = 0;
+ if (pthread_create(&tp[i]->td_id, NULL, rx_body, tp[i])) {
+ perror("unable to create thread");
+ exit(1);
+ }
+ }
+ return tp;
+}
+
+static void
+main_thread(struct td_desc **tp, int nsock, int nthreads)
+{
+ uint64_t c0, c1, bc0, bc1;
+ struct timespec now, then, delta;
+ /* now the parent collects and prints results */
+ c0 = c1 = bc0 = bc1 = 0;
+ clock_gettime(CLOCK_REALTIME, &then);
+ fprintf(stderr, "start at %ld.%09ld\n", then.tv_sec, then.tv_nsec);
+ while (1) {
+ int i, nt = nsock * nthreads;
+ int64_t dn;
+ uint64_t pps, bps;
+
+ if (poll(NULL, 0, 500) < 0)
+ perror("poll");
+ c0 = bc0 = 0;
+ for (i = 0; i < nt; i++) {
+ c0 += tp[i]->count;
+ bc0 += tp[i]->byte_count;
+ }
+ dn = c0 - c1;
+ clock_gettime(CLOCK_REALTIME, &now);
+ delta = now;
+ timespec_sub(&delta, &then);
+ then = now;
+ pps = dn;
+ pps = (pps * 1000000000) / (delta.tv_sec*1000000000 + delta.tv_nsec + 1);
+ bps = ((bc0 - bc1) * 8000000000) / (delta.tv_sec*1000000000 + delta.tv_nsec + 1);
+ fprintf(stderr, " %9ld pps %8.3f Mbps", (long)pps, .000001*bps);
+ fprintf(stderr, " - %d pkts in %ld.%09ld ns\n",
+ (int)dn, delta.tv_sec, delta.tv_nsec);
+ c1 = c0;
+ bc1 = bc0;
+ }
+}
+
int
main(int argc, char *argv[])
{
- struct sockaddr_in sin;
+ struct addrinfo hints, *res, *res0;
char *dummy, *packet;
- long port;
- int s, v;
+ int port;
+ int error, v, nthreads = 1;
+ struct td_desc **tp;
+ const char *cause = NULL;
+ int s[MAXSOCK];
+ int nsock;
- if (argc != 2)
+ if (argc < 2)
usage();
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE;
port = strtoul(argv[1], &dummy, 10);
if (port < 1 || port > 65535 || *dummy != '\0')
usage();
- sin.sin_port = htons(port);
+ if (argc > 2)
+ nthreads = strtoul(argv[2], &dummy, 10);
+ if (nthreads < 1 || nthreads > 64)
+ usage();
packet = malloc(65536);
if (packet == NULL) {
@@ -74,27 +228,48 @@
}
bzero(packet, 65536);
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if (s == -1) {
- perror("socket");
+ error = getaddrinfo(NULL, argv[1], &hints, &res0);
+ if (error) {
+ perror(gai_strerror(error));
return (-1);
+ /*NOTREACHED*/
}
- v = 128 * 1024;
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &v, sizeof(v)) < 0) {
- perror("SO_RCVBUF");
- return (-1);
+ nsock = 0;
+ for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
+ s[nsock] = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (s[nsock] < 0) {
+ cause = "socket";
+ continue;
+ }
+
+ v = 128 * 1024;
+ if (setsockopt(s[nsock], SOL_SOCKET, SO_RCVBUF, &v, sizeof(v)) < 0) {
+ cause = "SO_RCVBUF";
+ close(s[nsock]);
+ continue;
+ }
+ if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
+ cause = "bind";
+ close(s[nsock]);
+ continue;
+ }
+ (void) listen(s[nsock], 5);
+ nsock++;
}
-
- if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- perror("bind");
+ if (nsock == 0) {
+ perror(cause);
return (-1);
+ /*NOTREACHED*/
}
- printf("netreceive listening on UDP port %d\n", (u_short)port);
+ printf("netreceive %d sockets x %d threads listening on UDP port %d\n",
+ nsock, nthreads, (u_short)port);
- while (1) {
- if (recv(s, packet, 65536, 0) < 0)
- perror("recv");
- }
+ tp = make_threads(s, nsock, nthreads);
+ main_thread(tp, nsock, nthreads);
+
+ /*NOTREACHED*/
+ freeaddrinfo(res0);
}
More information about the Midnightbsd-cvs
mailing list