diff options
author | Mike Pattrick <mkp@redhat.com> | 2021-11-05 15:38:26 -0400 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2021-11-30 01:24:00 +0100 |
commit | 958ca7ba3b46000a9aff58f6b1fee8075e88cbf2 (patch) | |
tree | 5c3692d144c50a22e05f6bf8b8ee0f68a01da5e0 /utilities | |
parent | c60eec06492fd183a5801c6a22b990b2987f6846 (diff) | |
download | openvswitch-958ca7ba3b46000a9aff58f6b1fee8075e88cbf2.tar.gz |
ovs-tcpdump: Improve performance with dummy interface.
Currently the ovs-tcpdump utility creates a virtual tunnel to send
packets to. This method functions perfectly fine, however, it can
greatly impact performance of the monitored port.
It has been reported to reduce packet throughput significantly. I was
able to reproduce a reduction in throughput of up 70 percent in some
tests with a simple setup of two hosts communicating through a single
bridge on Linux with the kernel module datapath. Another more complex
test was configured for the usermode datapath both with and without
DPDK. This test involved a data path going from a VM, through a port
into one OVS bridge, out through a network card which could be DPDK
enabled for the relevant tests, in to a different network interface,
then into a different OVS bridge, through another port, and then into
a virtual machine.
Using the dummy driver resulted in the following impact to performance
compared to no ovs-tcpdump. Due to intra-test variance and fluctuations
during the first few seconds after installing a tap; multiple samples
were taken over multiple test runs. The first few seconds worth of
results were discarded and then results were averaged out.
If the dummy driver isn't present, falls back on the existing tap code.
Original Script
===============
Category Impact on Throughput
Kernel datapath - 65%
Usermode (no DPDK) - 26%
DPDK ports in use - 37%
New Script
==========
Category Impact on Throughput
Kernel datapath - 5%
Usermode (no DPDK) - 16%
DPDK ports in use - 29%
Signed-off-by: Mike Pattrick <mkp@redhat.com>
Acked-by: Aaron Conole <aconole@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'utilities')
-rwxr-xr-x | utilities/ovs-tcpdump.in | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/utilities/ovs-tcpdump.in b/utilities/ovs-tcpdump.in index 5ec02383c..82d1bedfa 100755 --- a/utilities/ovs-tcpdump.in +++ b/utilities/ovs-tcpdump.in @@ -14,15 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -import fcntl - import os import pwd from random import randint -import struct import subprocess import sys import time +import struct +import fcntl try: from netifaces import interfaces @@ -52,8 +51,8 @@ except Exception: print(" the correct location.") sys.exit(1) -tapdev_fd = None _make_taps = {} +_del_taps = {} _make_mirror_name = {} IFNAMSIZ_LINUX = 15 # this is the max name size, excluding the null byte. @@ -67,21 +66,25 @@ def _doexec(*args, **kwargs): return proc -def _install_tap_linux(tap_name, mtu_value=None): - """Uses /dev/net/tun to create a tap device""" - global tapdev_fd +def _install_dst_if_linux(tap_name, mtu_value=None): + ret_code = _doexec( + *['ip', 'link', 'add', str(tap_name), 'type', 'dummy'] + ).wait() - IFF_TAP = 0x0002 - IFF_NO_PI = 0x1000 - TUNSETIFF = 0x400454CA # This is derived by printf() of TUNSETIFF - TUNSETOWNER = TUNSETIFF + 2 + if ret_code != 0: + """If dummy driver is not present, fall back on /dev/net/tun""" + IFF_TAP = 0x0002 + IFF_NO_PI = 0x1000 + TUNSETIFF = 0x400454CA # This is derived by printf() of TUNSETIFF + TUNSETOWNER = TUNSETIFF + 2 - tapdev_fd = os.open('/dev/net/tun', os.O_RDWR) - ifr = struct.pack('16sH', tap_name.encode('utf8'), IFF_TAP | IFF_NO_PI) - fcntl.ioctl(tapdev_fd, TUNSETIFF, ifr) - fcntl.ioctl(tapdev_fd, TUNSETOWNER, os.getegid()) + tapdev_fd = os.open('/dev/net/tun', os.O_RDWR) + ifr = struct.pack('16sH', tap_name.encode('utf8'), IFF_TAP | IFF_NO_PI) + fcntl.ioctl(tapdev_fd, TUNSETIFF, ifr) + fcntl.ioctl(tapdev_fd, TUNSETOWNER, os.getegid()) + + time.sleep(1) # required to give the new device settling time - time.sleep(1) # required to give the new device settling time if mtu_value is not None: pipe = _doexec( *(['ip', 'link', 'set', 'dev', str(tap_name), 'mtu', @@ -93,14 +96,22 @@ def _install_tap_linux(tap_name, mtu_value=None): pipe.wait() +def _remove_dst_if_linux(tap_name): + _doexec( + *['ip', 'link', 'del', str(tap_name)] + ).wait() + + def _make_linux_mirror_name(interface_name): if len(interface_name) > IFNAMSIZ_LINUX - 2: return "ovsmi%06d" % randint(1, 999999) return "mi%s" % interface_name -_make_taps['linux'] = _install_tap_linux -_make_taps['linux2'] = _install_tap_linux +_make_taps['linux'] = _install_dst_if_linux +_make_taps['linux2'] = _install_dst_if_linux +_del_taps['linux'] = _remove_dst_if_linux +_del_taps['linux2'] = _remove_dst_if_linux _make_mirror_name['linux'] = _make_linux_mirror_name _make_mirror_name['linux2'] = _make_linux_mirror_name @@ -455,6 +466,9 @@ def main(): mirror_interface not in interfaces(): _make_taps[sys.platform](mirror_interface, ovsdb.interface_mtu(interface)) + tap_created = True + else: + tap_created = False if mirror_interface not in interfaces(): print("ERROR: Please create an interface called `%s`" % @@ -480,6 +494,8 @@ def main(): print("ERROR: Unable to properly setup the mirror: %s." % str(oe)) try: ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) + if tap_created is True: + _del_taps[sys.platform](mirror_interface) except Exception: pass sys.exit(1) @@ -498,6 +514,8 @@ def main(): ovsdb.destroy_mirror(interface, ovsdb.port_bridge(interface)) ovsdb.destroy_port(mirror_interface, ovsdb.port_bridge(interface)) + if tap_created is True: + _del_taps[sys.platform](mirror_interface) except Exception: print("Unable to tear down the ports and mirrors.") print("Please use ovs-vsctl to remove the ports and mirrors created.") |