Mike Pattrick <[email protected]> writes:

> 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 <[email protected]>
> ---
>  utilities/ovs-tcpdump.in | 54 ++++++++++++++++++++++++++--------------
>  1 file 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)

Will this be okay when we close if we drop into the tap code fallback?
I assume yes, but just want to be sure.  Assuming it does

Acked-by: Aaron Conole <[email protected]>

>      except Exception:
>          print("Unable to tear down the ports and mirrors.")
>          print("Please use ovs-vsctl to remove the ports and mirrors 
> created.")

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to