Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jun 2015 02:59:31 GMT
From:      btw@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r286504 - in soc2015/btw/head/tools/tools/mq-testing: . udp
Message-ID:  <201506010259.t512xVN8041711@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: btw
Date: Mon Jun  1 02:59:31 2015
New Revision: 286504
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=286504

Log:
  Add the tools for multiqueue testing:
  
  - pktgen: a UDP packet generator based on vme;
  - server: a UDP server based on socket(2);

Added:
  soc2015/btw/head/tools/tools/mq-testing/README
  soc2015/btw/head/tools/tools/mq-testing/udp/
  soc2015/btw/head/tools/tools/mq-testing/udp/Makefile
  soc2015/btw/head/tools/tools/mq-testing/udp/common.h
  soc2015/btw/head/tools/tools/mq-testing/udp/pktgen.c
  soc2015/btw/head/tools/tools/mq-testing/udp/server.c

Added: soc2015/btw/head/tools/tools/mq-testing/README
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/btw/head/tools/tools/mq-testing/README	Mon Jun  1 02:59:31 2015	(r286504)
@@ -0,0 +1,4 @@
+$FreeBSD$
+
+This directory contains the applications for multiqueue testing.
+

Added: soc2015/btw/head/tools/tools/mq-testing/udp/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/btw/head/tools/tools/mq-testing/udp/Makefile	Mon Jun  1 02:59:31 2015	(r286504)
@@ -0,0 +1,12 @@
+
+PROGS:= server pktgen
+CFLAGS:= -Wall -Werror -O2 -lpthread
+
+all: ${PROGS}
+
+server:
+
+pktgen:
+
+clean:
+	rm -f *.o ${PROGS}

Added: soc2015/btw/head/tools/tools/mq-testing/udp/common.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/btw/head/tools/tools/mq-testing/udp/common.h	Mon Jun  1 02:59:31 2015	(r286504)
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2015, Tiwei Bie <btw@mail.ustc.edu.cn>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#define SERVER_PORT 8000
+
+#endif

Added: soc2015/btw/head/tools/tools/mq-testing/udp/pktgen.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/btw/head/tools/tools/mq-testing/udp/pktgen.c	Mon Jun  1 02:59:31 2015	(r286504)
@@ -0,0 +1,299 @@
+/*-
+ * Copyright (c) 2015, Tiwei Bie <btw@mail.ustc.edu.cn>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD$ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ifaddrs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <pthread_np.h>
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/cpuset.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+
+#include "common.h"
+
+/*
+ * TODO:
+ * #1. Add supports for IPv6;
+ */
+#define IFCONFIG_BIN  "/sbin/ifconfig "
+#define IFCONFIG_ARGS "%s inet %s"
+
+static char vmedev[MAXPATHLEN];
+static uint8_t vmeif_ether[ETHER_ADDR_LEN];
+static in_addr_t vmeif_ip;
+
+static char vmeif_name[IFNAMSIZ] = "vme0";
+static char vmeif_ipstr[256] = "192.168.10.1";
+static char *payload = "hello, world!";
+static int pktsize = 100;
+static int quiet = 0;
+static int cpu = -1;
+static uint64_t total_sent = 0;
+
+/* The checksum function is taken from tools/tools/netmap/pkt-gen.c */
+static uint16_t
+checksum(const void *data, uint16_t len, uint32_t sum)
+{
+	const uint8_t *addr = data;
+	uint32_t i;
+
+	/* Checksum all the pairs of bytes first... */
+	for (i = 0; i < (len & ~1U); i += 2) {
+		sum += (uint16_t)ntohs(*(uint16_t *)(addr + i));
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	/*
+	 * If there's a single byte left over, checksum it, too.
+	 * Network byte order is big-endian, so the remaining byte is
+	 * the high byte.
+	 */
+	if (i < len) {
+		sum += addr[i] << 8;
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	return (sum);
+}
+
+static uint16_t
+wrapsum(uint32_t sum)
+{
+	sum = ~sum & 0xFFFF;
+	return (htons(sum));
+}
+
+static inline int
+min(int a, int b)
+{
+	return (a < b) ? a : b;
+}
+
+static void
+build_udp_packet(uint8_t *buf, int pkt_size)
+{
+	struct ether_header *eh = (struct ether_header *)buf;
+	struct ip *ip = (struct ip *)(eh + 1);
+	struct udphdr *udp = (struct udphdr *)(ip + 1);
+	char *data = (char *)(udp + 1);
+
+	/* Just fake an address */
+	eh->ether_shost[0] = 0x01;
+	eh->ether_shost[1] = 0xbd;
+	eh->ether_shost[2] = 0xbc;
+	eh->ether_shost[3] = 0x4d;
+	eh->ether_shost[4] = 0xfb;
+	eh->ether_shost[5] = 0xfb;
+	memcpy(eh->ether_dhost, vmeif_ether, ETHER_ADDR_LEN);
+	eh->ether_type = htons(ETHERTYPE_IP);
+
+	ip->ip_v = IPVERSION;
+	ip->ip_hl = sizeof(*ip) >> 2;
+	ip->ip_tos = IPTOS_LOWDELAY;
+	ip->ip_len = htons(pkt_size - sizeof(*eh));
+	ip->ip_id = 0;
+	ip->ip_off = htons(IP_DF); /* XXX: Don't fragment */
+	ip->ip_ttl = IPDEFTTL;
+	ip->ip_p = IPPROTO_UDP;
+	ip->ip_src.s_addr = htonl(0x0a000001 + (rand() % 0xfffffe));
+	ip->ip_dst.s_addr = vmeif_ip;
+
+	ip->ip_sum = 0;
+	ip->ip_sum = wrapsum(checksum(ip, sizeof(*ip), 0));
+
+	udp->uh_sport = htons(1 + rand() % 65535);
+	udp->uh_dport = htons(SERVER_PORT);
+	udp->uh_ulen = htons(pkt_size - sizeof(*eh) - sizeof(*ip));
+	udp->uh_sum = 0;
+
+	memcpy(data, payload, min(strlen(payload) + 1,
+	    pkt_size - (sizeof(*eh) + sizeof(*ip) + sizeof(*udp))));
+}
+
+static int
+get_ifaddr(const char *ifname, uint8_t *ether_addr)
+{
+	struct ifaddrs *ifa, *p;
+	struct sockaddr_dl *sdl;
+	char *addr;
+	int error = -1;
+
+	if (getifaddrs(&ifa) != 0)
+		return (-1);
+
+	for (p = ifa; p != NULL; p = p->ifa_next) {
+		if (strcmp(p->ifa_name, ifname) == 0 &&
+		    p->ifa_addr->sa_family == AF_LINK &&
+		    p->ifa_data != NULL) {
+			sdl = (struct sockaddr_dl *)p->ifa_addr;
+			addr = &sdl->sdl_data[sdl->sdl_nlen];
+			memcpy(ether_addr, addr, ETHER_ADDR_LEN);
+			error = 0;
+			break;
+		}
+	}
+
+	freeifaddrs(ifa);
+	return (error);
+}
+
+static void
+bind_cpu(int cpu)
+{
+	cpuset_t mask;
+
+	CPU_ZERO(&mask);
+	CPU_SET(cpu, &mask);
+	if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) != 0)
+		perror("pthread_setaffinity_np");
+}
+
+static void
+signal_handler(int arg)
+{
+	printf("\r%lu packets injected.\n", total_sent);
+
+	if (arg == SIGINT)
+		exit(EXIT_SUCCESS);
+}
+
+static void
+usage(const char *prgname)
+{
+	fprintf(stderr, "%s [-a ip address] [-i vme interface] [-l pktsize] "
+	    "[-p payload] [-q]\n", prgname);
+	exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char **argv)
+{
+	int vmefd;
+	char cmd[sizeof(IFCONFIG_BIN) + sizeof(vmeif_name) +
+		 sizeof(vmeif_ipstr) + 50];
+	uint8_t *buf;
+	int ch;
+
+	while ((ch = getopt(argc, argv, "a:b:i:l:p:q")) != -1) {
+		switch (ch) {
+		case 'a':
+			strlcpy(vmeif_ipstr, optarg, sizeof(vmeif_ipstr));
+			break;
+		case 'b':
+			sscanf(optarg, "%d", &cpu);
+			break;
+		case 'i':
+			strlcpy(vmeif_name, optarg, sizeof(vmeif_name));
+			break;
+		case 'l':
+			sscanf(optarg, "%d", &pktsize);
+			break;
+		case 'p':
+			payload = strdup(optarg);
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	}
+
+	if (!quiet) {
+		printf("vme name: %s\n", vmeif_name);
+		printf("vme ip: %s\n", vmeif_ipstr);
+		printf("packet size: %d\n", pktsize);
+		printf("payload: %s\n", payload);
+		if (cpu != -1)
+			printf("cpu: %d\n", cpu);
+	}
+
+	if (cpu != -1)
+		bind_cpu(cpu);
+
+	signal(SIGINT, signal_handler);
+
+	snprintf(vmedev, sizeof(vmedev), "/dev/%s", vmeif_name);
+
+	vmefd = open(vmedev, O_RDWR);
+	if (vmefd == -1) {
+		fprintf(stderr, "Failed to open %s: %s\n", vmedev,
+		    strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	snprintf(cmd, sizeof(cmd), IFCONFIG_BIN IFCONFIG_ARGS, vmeif_name,
+	    vmeif_ipstr);
+	if (system(cmd) != 0) {
+		fprintf(stderr, "Failed to setup %s\n", vmeif_name);
+		exit(EXIT_FAILURE);
+	}
+
+	if ((vmeif_ip = inet_addr(vmeif_ipstr)) == INADDR_NONE) {
+		fprintf(stderr, "Malformed address %s specified\n",
+		    vmeif_ipstr);
+		exit(EXIT_FAILURE);
+	}
+
+	if (get_ifaddr(vmeif_name, vmeif_ether) != 0) {
+		fprintf(stderr, "Failed to get %s's MAC address\n", vmeif_name);
+		exit(EXIT_FAILURE);
+	}
+
+	if ((buf = malloc(pktsize)) == NULL) {
+		perror("Failed to allocate memory for packet");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Keep injecting packets to network stack */
+	while (1) {
+		build_udp_packet(buf, pktsize);
+		if (write(vmefd, buf, pktsize) == -1) {
+			perror("write");
+			exit(EXIT_FAILURE);
+		}
+		total_sent++;
+	}
+
+	return (0);
+}

Added: soc2015/btw/head/tools/tools/mq-testing/udp/server.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2015/btw/head/tools/tools/mq-testing/udp/server.c	Mon Jun  1 02:59:31 2015	(r286504)
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2015, Tiwei Bie <btw@mail.ustc.edu.cn>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* $FreeBSD$ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "common.h"
+
+static int verbose = 0;
+
+static void
+usage(const char *prgname)
+{
+	fprintf(stderr, "%s [-v]\n", prgname);
+	exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char **argv)
+{
+	int sd;
+	struct sockaddr_in lsin, from;
+	socklen_t length;
+	char msg[BUFSIZ];
+	int n, ch, i;
+
+	while ((ch = getopt(argc, argv, "v")) != -1) {
+		switch (ch) {
+		case 'v':
+			verbose = 1;
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	}
+
+	sd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sd < 0) {
+		perror("socket");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(&lsin, 0, sizeof(lsin));
+	lsin.sin_family = AF_INET;
+	lsin.sin_addr.s_addr = INADDR_ANY;
+	lsin.sin_port = htons(SERVER_PORT);
+	if (bind(sd, (struct sockaddr *)&lsin, sizeof(lsin)) < 0) {
+		perror("bind");
+		exit(EXIT_FAILURE);
+	}
+
+	while (1) {
+		length = sizeof(from);
+		n = recvfrom(sd, msg, sizeof(msg), 0,
+		    (struct sockaddr *)&from, &length);
+		if (n < 0) {
+			perror("recvfrom");
+			exit(EXIT_FAILURE);
+		}
+
+		if (verbose) {
+			printf("from=%s:%d len=%d  ", inet_ntoa(from.sin_addr),
+			    ntohs(from.sin_port), n);
+			for (i = 0; i < n && msg[i]; i++) {
+				if (isprint(msg[i]))
+					printf("%c", msg[i]);
+			}
+			printf("\n");
+		}
+	}
+
+	return (0);
+}



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