Hi Misc,

I'm making some trials and benchmarks about pf's divert. My test environment is 
like this;

I have 2 Linux devices and I have an OpenBSD device which are directly 
connected to an OpenBSD Device. This OpenBSD device acts likes a router.

Network settings in OpenBSD:
---------
vertigo# ifconfig em1
em1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:30:18:0a:a6:2e
index 2 priority 0 llprio 3
media: Ethernet autoselect (1000baseT full-duplex,rxpause,txpause)
status: active
inet 172.20.35.1 netmask 0xffffff00 broadcast 172.20.35.255
vertigo# ifconfig em2
em2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:30:18:0a:a6:2f
index 3 priority 0 llprio 3
media: Ethernet autoselect (1000baseT full-duplex,rxpause,txpause)
status: active
inet 172.20.36.1 netmask 0xffffff00 broadcast 172.20.36.255
vertigo#
-------
-------
vertigo# sysctl net.inet.ip.forwarding
net.inet.ip.forwarding=1
-------
my pf.conf is like this;
-----------
vertigo# cat /etc/pf.conf
# $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf

set skip on lo
# em1
pass in log quick on em1 from em1:network to172.20.36.0/24
pass out log quick on em1 from172.20.36.0/24to em1:network
# em2
pass in log quick on em2 from em2:network to172.20.35.0/24
pass out log quick on em2 from172.20.35.0/24to em2:network
# block all
block log quick all
block return # block stateless traffic
pass # establish keep-state

# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010

# Port build user does not need network
block return out log proto {tcp udp} user _pbuild
--------

On Linux-1, I'm making benchmark tests to Linux-2 with qperf,

--------
vertigo@linux1:~$ qperf 172.20.35.2 tcp_bw tcp_lat -t 10
tcp_bw:
bw = 115 MB/sec
tcp_lat:
latency = 157 us
vertigo@linux1:~$ qperf 172.20.35.2 udp_bw udp_lat -t 10
udp_bw:
send_bw = 120 MB/sec
recv_bw = 120 MB/sec
udp_lat:
latency = 158 us
vertigo@linux1:~$
---------
After that, I updated the pf.conf and diverted packages to port 700

------
vertigo# cat /etc/pf.conf
# $OpenBSD: pf.conf,v 1.55 2017/12/03 20:40:04 sthen Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf

set skip on lo
# em1
pass in log quick on em1 from em1:network to172.20.36.0/24
pass out log quick on em1 from172.20.36.0/24to em1:network divert-packet port 
700
# em2
pass in log quick on em2 from em2:network to172.20.35.0/24
pass out log quick on em2 from172.20.35.0/24to em2:network divert-packet port 
700
# block all
block log quick all
block return # block stateless traffic
pass # establish keep-state

# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010

# Port build user does not need network
block return out log proto {tcp udp} user _pbuild
------
On port 700, I run the example program on OpenBSD divert manpage.
https://man.openbsd.org/divert.4
-----

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <err.h>

#define DIVERT_PORT 700

int
main(int argc, char *argv[])
{
        int fd, s;
        struct sockaddr_in sin;
        socklen_t sin_len;

        fd = socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
        if (fd == -1)
                err(1, "socket");

        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(DIVERT_PORT);
        sin.sin_addr.s_addr = 0;

        sin_len = sizeof(struct sockaddr_in);

        s = bind(fd, (struct sockaddr *) &sin, sin_len);
        if (s == -1)
                err(1, "bind");

        for (;;) {
                ssize_t n;
                char packet[IP_MAXPACKET];
                struct ip *ip;
                struct tcphdr *th;
                int hlen;
                char src[48], dst[48];

                memset(packet, 0, sizeof(packet));
                n = recvfrom(fd, packet, sizeof(packet), 0,
                (struct sockaddr *) &sin, &sin_len);
                if (n == -1) {
                        warn("recvfrom");
                        continue;
                }
                if (n < sizeof(struct ip)) {
                        warnx("packet is too short");
                        continue;
                }

                ip = (struct ip *) packet;
                hlen = ip->ip_hl << 2;
                if (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen ||
                n < ntohs(ip->ip_len)) {
                        warnx("invalid IPv4 packet");
                        continue;
                }

                th = (struct tcphdr *) (packet + hlen);

                if (inet_ntop(AF_INET, &ip->ip_src, src,
                sizeof(src)) == NULL)
                        (void)strlcpy(src, "?", sizeof(src));

                if (inet_ntop(AF_INET, &ip->ip_dst, dst,
                sizeof(dst)) == NULL)
                        (void)strlcpy(dst, "?", sizeof(dst));

                printf("%s:%u -> %s:%u\n",
                src,
                ntohs(th->th_sport),
                dst,
                ntohs(th->th_dport)
                );

                n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin,
                sin_len);
                if (n == -1)
                        warn("sendto");
        }

        return 0;
}

And I made the same test again;
There is a big difference in TCP benchmark tests,
I repeated the tests, but the results did not change.

---------
vertigo@linux1:~$ qperf 172.20.35.2 tcp_bw tcp_lat -t 10
tcp_bw:
bw = 32.6 KB/sec
tcp_lat:
latency = 214 us
vertigo@linux1:~$ qperf 172.20.35.2 udp_bw udp_lat -t 10
udp_bw:
send_bw = 120 MB/sec
recv_bw = 111 MB/sec
udp_lat:
latency = 214 us
vertigo@linux1:~$
----------
I could not understand why this big difference occurs. Is there any way to 
improve "divert" s performance?

Sent with [ProtonMail](https://protonmail.com) Secure Email.

Reply via email to