diff options
author | Martin KaFai Lau <kafai@fb.com> | 2014-12-02 10:41:46 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-09 13:04:28 -0500 |
commit | 160062b65d99e1b55efd957e7bc1076e530c8679 (patch) | |
tree | 514c0823b18577db2d0b7e590c5cc575f197eec8 | |
parent | 78857d275e71d5ee4905d6994d1cbb744c3f9f1c (diff) | |
download | net_test_tools-160062b65d99e1b55efd957e7bc1076e530c8679.tar.gz |
udpflood: Add IPv6 support
This patch:
1. Add IPv6 support
2. Print timing for every 65536 fib insert operations to observe
the gc effect (mostly for IPv6 fib).
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | udpflood.c | 125 |
1 files changed, 101 insertions, 24 deletions
@@ -6,7 +6,9 @@ #include <string.h> #include <errno.h> #include <unistd.h> +#include <stdint.h> +#include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -15,57 +17,121 @@ #define _GNU_SOURCE #include <getopt.h> +static int debug = 0; + +typedef union sa_u { + struct sockaddr_in a4; + struct sockaddr_in6 a6; +} sa_u; + static int usage(void) { printf("usage: udpflood [ -l count ] [ -m message_size ] [ -c num_ip_addrs ] IP_ADDRESS\n"); return -1; } -static int send_packets(in_addr_t start_addr, in_addr_t end_addr, - int port, int count, int msg_sz) +static uint32_t get_last32h(const sa_u *sa) +{ + if (sa->a4.sin_family == PF_INET) + return ntohl(sa->a4.sin_addr.s_addr); + else + return ntohl(sa->a6.sin6_addr.s6_addr32[3]); +} + +static void set_last32h(sa_u *sa, uint32_t last32h) +{ + if (sa->a4.sin_family == PF_INET) + sa->a4.sin_addr.s_addr = htonl(last32h); + else + sa->a6.sin6_addr.s6_addr32[3] = htonl(last32h); +} + +static void print_sa(const sa_u *sa, const char *msg) +{ + char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; + + if (!debug) + return; + + switch (sa->a4.sin_family) { + case PF_INET: + inet_ntop(PF_INET, &(sa->a4.sin_addr.s_addr), buf, + sizeof(buf)); + break; + case PF_INET6: + inet_ntop(PF_INET6, sa->a6.sin6_addr.s6_addr, buf, sizeof(buf)); + break; + } + + printf("%s: %s\n", msg, buf); +} + +static long get_diff_ms(const struct timeval *now, + const struct timeval *start) +{ + long start_ms, now_ms; + start_ms = start->tv_sec * 1000 + (start->tv_usec / 1000); + now_ms = now->tv_sec * 1000 + (now->tv_usec / 1000); + return now_ms - start_ms; +} + +static int send_packets(const sa_u *start_sa, size_t num_addrs, int count, + int msg_sz) { char *msg = malloc(msg_sz); - struct sockaddr_in saddr; - in_addr_t addr; + sa_u cur_sa; + uint32_t start_addr32h, end_addr32h, cur_addr32h; int fd, i, err; + struct timeval last, now; if (!msg) return -ENOMEM; memset(msg, 0, msg_sz); - addr = start_addr; - - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = port; - saddr.sin_addr.s_addr = addr; + memcpy(&cur_sa, start_sa, sizeof(cur_sa)); + cur_addr32h = start_addr32h = get_last32h(&cur_sa); + end_addr32h = start_addr32h + num_addrs; - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + fd = socket(cur_sa.a4.sin_family, SOCK_DGRAM, IPPROTO_IP); if (fd < 0) { perror("socket"); err = fd; goto out_nofd; } - err = connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)); + err = connect(fd, (struct sockaddr *) &cur_sa, sizeof(cur_sa)); if (err < 0) { perror("connect"); - close(fd); goto out; } + print_sa(start_sa, "start_addr"); + gettimeofday(&last, NULL); for (i = 0; i < count; i++) { - saddr.sin_addr.s_addr = addr; - + print_sa(&cur_sa, "sendto"); err = sendto(fd, msg, msg_sz, 0, - (struct sockaddr *) &saddr, sizeof(saddr)); + (struct sockaddr *) &cur_sa, sizeof(cur_sa)); if (err < 0) { perror("sendto"); goto out; } - if (++addr >= end_addr) - addr = start_addr; + if (++cur_addr32h >= end_addr32h) + cur_addr32h = start_addr32h; + set_last32h(&cur_sa, cur_addr32h); + + /* + * print timing info for every 65536 fib inserts to + * observe the gc effect (mostly for IPv6 fib). + */ + if (i && (i & 0xFFFF) == 0) { + long diff_ms; + gettimeofday(&now, NULL); + diff_ms = get_diff_ms(&now, &last); + printf("%d %ld.%ld\n", i >> 16, + diff_ms / 1000, diff_ms % 1000); + memcpy(&last, &now, sizeof(last)); + } } err = 0; @@ -79,14 +145,14 @@ out_nofd: int main(int argc, char **argv, char **envp) { int port, msg_sz, count, num_addrs, ret; - in_addr_t start_addr, end_addr; + sa_u start_sa; port = 6000; msg_sz = 32; count = 10000000; num_addrs = 1; - while ((ret = getopt(argc, argv, "l:s:p:c:")) >= 0) { + while ((ret = getopt(argc, argv, "dl:s:p:c:")) >= 0) { switch (ret) { case 'l': sscanf(optarg, "%d", &count); @@ -100,18 +166,29 @@ int main(int argc, char **argv, char **envp) case 'c': sscanf(optarg, "%d", &num_addrs); break; + case 'd': + debug = 1; + break; case '?': return usage(); } } + if (num_addrs < 1 || count < 1) + return usage(); + if (!argv[optind]) return usage(); - start_addr = inet_addr(argv[optind]); - if (start_addr == INADDR_NONE) + memset(&start_sa, 0, sizeof(start_sa)); + start_sa.a4.sin_port = htons(port); + if (inet_pton(PF_INET, argv[optind], &start_sa.a4.sin_addr)) + start_sa.a4.sin_family = PF_INET; + else if (inet_pton(PF_INET6, argv[optind], + start_sa.a6.sin6_addr.s6_addr)) + start_sa.a6.sin6_family = PF_INET6; + else return usage(); - end_addr = start_addr + num_addrs; - return send_packets(start_addr, end_addr, port, count, msg_sz); + return send_packets(&start_sa, num_addrs, count, msg_sz); } |