socsvn commit: r286504 - in soc2015/btw/head/tools/tools/mq-testing: . udp
btw at FreeBSD.org
btw at FreeBSD.org
Mon Jun 1 02:59:33 UTC 2015
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 at 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 at 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 at 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);
+}
More information about the svn-soc-all
mailing list