summaryrefslogtreecommitdiff
path: root/utilities
diff options
context:
space:
mode:
authorMike Pattrick <mkp@redhat.com>2021-11-05 15:38:26 -0400
committerIlya Maximets <i.maximets@ovn.org>2021-11-30 01:24:00 +0100
commit958ca7ba3b46000a9aff58f6b1fee8075e88cbf2 (patch)
tree5c3692d144c50a22e05f6bf8b8ee0f68a01da5e0 /utilities
parentc60eec06492fd183a5801c6a22b990b2987f6846 (diff)
downloadopenvswitch-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-xutilities/ovs-tcpdump.in54
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.")