in testing tap(4)  performance on the same box with the following config
using claudios userlandbridge (tbridge)  in between two tap interfaces
each tap was also added their own standard bridge(4) along with 1 physical
interface.

iperf3client--ix0--bridge0--tap0--tbridge--tap1--bridge1--ix1---iperf3svr

with a 1socket 2 core system that gives 3Gb/s we got the following
performance

tbridge -t gave 557Mb/s TCP throughput

btw (tbridge -t did not stop after  using ^C  or kill
but did respond to kill -s SIGKILL )

tbridge -s gave 455Mb/s TCP throughput

tbridge -p gave 448Mb/s TCP throughput

tbridge -k gave 458mb/s TCP througput

im going to try this again with more CPUs as the workload of forwarding in
this box involves 3 bridges in series.

I will also try with the tpmr(4) driver
so something about OpenVPN  has a bottleneck that reduces performance
by a factor of 3 -4x








---------- Forwarded message ---------
From: Tom Smyth <[email protected]>
Date: Tue, 21 Jan 2020 at 11:15
Subject: Re: tap(4) performance tuning on (amd64)
To: Tom Smyth <[email protected]>, Misc <[email protected]>


Thanks Claudio,

the program now seems to run without exiting ...  Ill do some tests
and get back to you
later
Tom Smyth

On Tue, 21 Jan 2020 at 03:09, Claudio Jeker <[email protected]>
wrote:
>
> On Tue, Jan 21, 2020 at 02:44:35AM +0000, Tom Smyth wrote:
> > Claudio,
> > Thanks for this,
> > I compiled  it on Openbsd 6.6 (stable) amd64
> >
> > it compiled without error
> >
> > the binary seems to run  fine but,
> > ./tbridge -k /dev/tap0 /dev/tap1
> >
> > runs and displays the usage message and  gives an errorlevel of 1
> > every time  use the -k or -t or -s or -p arguments   see  terminal
> > conversation below
> >
>
> Shit, I added a last minute check and as usual introduced a bug.
> Line 189 change if (ch != 0) to if (mode != 0)
>
> --
> :wq Claudio
>
> /*
>  * Copyright (c) 2020 Claudio Jeker <[email protected]>
>  *
>  * Permission to use, copy, modify, and distribute this software for any
>  * purpose with or without fee is hereby granted, provided that the above
>  * copyright notice and this permission notice appear in all copies.
>  *
>  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES
>  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>  */
> #include <sys/types.h>
> #include <sys/event.h>
> #include <sys/time.h>
>
> #include <err.h>
> #include <errno.h>
> #include <fcntl.h>
> #include <poll.h>
> #include <pthread.h>
> #include <signal.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
>
> volatile sig_atomic_t    quit;
>
> static void
> do_read(int in, int out)
> {
>         char buf[2048];
>         ssize_t n, o;
>
>         n = read(in, buf, sizeof(buf));
>         if (n == -1)
>                 err(1, "read");
>         o = write(out, buf, n);
>         if (o == -1)
>                 err(1, "read");
>         if (o != n)
>                 errx(1, "short write");
> }
>
> static void
> do_poll(int fd[2])
> {
>         struct pollfd pfd[2];
>         int n, i;
>
>         while (quit == 0) {
>                 memset(pfd, 0, sizeof(pfd));
>                 pfd[0].fd = fd[0];
>                 pfd[0].events = POLLIN;
>
>                 pfd[1].fd = fd[1];
>                 pfd[1].events = POLLIN;
>
>                 n = poll(pfd, 2, INFTIM);
>                 if (n == -1)
>                         err(1, "poll");
>                 if (n == 0)
>                         errx(1, "poll: timeout");
>                 for (i = 0; i < 2; i++) {
>                         if (pfd[i].revents & POLLIN)
>                                 do_read(fd[i], fd[(i + 1) & 0x1]);
>                         else if (pfd[i].revents & (POLLHUP | POLLERR))
>                                 errx(1, "fd %d revents %x", i,
pfd[i].revents);
>                 }
>         }
>
> }
>
> static void
> do_select(int fd[2])
> {
>         fd_set readfds;
>         int n, i, maxfd = -1;
>
>         while (quit == 0) {
>                 FD_ZERO(&readfds);
>                 for (i = 0; i < 2; i++) {
>                         if (fd[i] > maxfd)
>                                 maxfd = fd[i];
>                         FD_SET(fd[i], &readfds);
>                 }
>                 n = select(maxfd + 1, &readfds, NULL, NULL, NULL);
>                 if (n == -1)
>                         err(1, "select");
>                 if (n == 0)
>                         errx(1, "select: timeout");
>                 for (i = 0; i < 2; i++) {
>                         if (FD_ISSET(fd[i], &readfds))
>                                 do_read(fd[i], fd[(i + 1) & 0x1]);
>                 }
>         }
> }
>
> static void
> do_kqueue(int fd[2])
> {
>         struct kevent kev[2];
>         int kq, i, n;
>
>         if ((kq = kqueue()) == -1)
>                 err(1, "kqueue");
>
>         memset(kev, 0, sizeof(kev));
>         for (i = 0; i < 2; i++) {
>                 EV_SET(&kev[i], fd[i], EVFILT_READ, EV_ADD | EV_ENABLE,
>                     0, 0, (void *)(intptr_t)i);
>         }
>         if (kevent(kq, kev, 2, NULL, 0, NULL) == -1)
>                 err(1, "kevent register");
>
>         while (quit == 0) {
>                 n = kevent(kq, NULL, 0, kev, 2, NULL);
>                 if (n == -1)
>                         err(1, "kevent");
>                 if (n == 0)
>                         errx(1, "kevent: timeout");
>                 for (i = 0; i < n; i++) {
>                         if (kev[i].flags & EV_ERROR)
>                                 errc(1, kev[i].data, "kevent EV_ERROR");
>                         if (kev[i].filter == EVFILT_READ) {
>                                 int r = (int)kev[i].udata;
>                                 do_read(fd[r], fd[(r + 1) & 0x1]);
>                         }
>                 }
>         }
> }
>
> static void *
> run_thread(void *arg)
> {
>         int *fd = arg;
>
>         while (quit == 0)
>                 do_read(fd[0], fd[1]);
>
>         return NULL;
> }
>
> static void
> do_thread(int fd[2])
> {
>         pthread_t tid;
>         int ret;
>
>         ret = pthread_create(&tid, NULL, run_thread, fd);
>         if (ret)  {
>                 errc(1, ret, "pthread_create");
>         }
>
>         while (quit == 0)
>                 do_read(fd[1], fd[0]);
> }
>
> static void
> sighdlr(int sig)
> {
>         quit = 1;
> }
>
> static __dead void
> usage(void)
> {
>         fprintf(stderr, "tbridge -k | -p | -s | -t tapA tapB\n");
>         exit(1);
> }
>
> int
> main(int argc, char **argv)
> {
>         int fd[2];
>         int ch = 0;
>         int mode = 0;
>
>         while ((ch = getopt(argc, argv, "kpst")) != -1) {
>                 switch (ch) {
>                 case 'k':
>                 case 'p':
>                 case 's':
>                 case 't':
>                         if (mode != 0)
>                                 usage();
>                         mode = ch;
>                         break;
>                 default:
>                         usage();
>                 }
>         }
>         argc -= optind;
>         argv += optind;
>         if (argc != 2)
>                 usage();
>
>         signal(SIGTERM, sighdlr);
>         signal(SIGINT, sighdlr);
>         signal(SIGHUP, sighdlr);
>
>         fd[0] = open(argv[0], O_RDWR);
>         if (fd[0] == -1)
>                 err(1, "open %s", argv[1]);
>
>         fd[1] = open(argv[1], O_RDWR);
>         if (fd[1] == -1)
>                 err(1, "open %s", argv[2]);
>
>         switch (mode) {
>         case 'k':
>                 do_kqueue(fd);
>                 break;
>         case 'p':
>                 do_poll(fd);
>                 break;
>         case 's':
>                 do_select(fd);
>                 break;
>         case 't':
>                 do_thread(fd);
>                 break;
>         }
>         exit(0);
> }



--
Kindest regards,
Tom Smyth.


-- 
Kindest regards,
Tom Smyth.

Reply via email to