Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/if.py: refactor module #3905

Merged
merged 7 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file.
68 changes: 68 additions & 0 deletions virttest/vt_utils/net/drivers/bridge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Library for the bridge address related functions.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat (c) 2024 and Avocado contributors
# Author: Houqi Zuo <[email protected]>
import json

from avocado.utils import process

from virttest.vt_utils.net import interface


def find_bridge_name(iface):
"""
Finds bridge name based in the interface name.

:param iface: The interface name.
:type iface: String.

:return: The bridge name. If not found, return None.
:rtype: String or None.
"""
cmd = "bridge -json link"
cmd_obj = process.run(cmd, shell=True)
output = cmd_obj.stdout_text.strip()
bridge_info = json.loads(output)
for bridge in bridge_info:
if bridge["ifname"] in (iface,):
return bridge["master"]
return None


def add_to_bridge(ifname, brname):
"""
Add the interface into the bridge.

:param ifname: The interface name.
:type ifname: String.

:param brname: The bridge name.
:type brname: String.
"""
# To add an interface into the bridge, its state must be up.
interface.bring_up_ifname(ifname)
cmd_add_to_bridge = "ip link set %s master %s" % (ifname, brname)
process.run(cmd_add_to_bridge, shell=True)


def del_from_bridge(ifname):
"""
Delete the interface from the bridge.
NOTE: Bringing the interface down is excluded at this function.
You may call the function about bringing interface down after del_from_bridge().

:param ifname: The interface name.
:type ifname: String.
"""
cmd = "ip link set %s nomaster" % ifname
process.run(cmd, shell=True)
126 changes: 126 additions & 0 deletions virttest/vt_utils/net/drivers/macvtap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Library for the macvtap address related functions.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat (c) 2024 and Avocado contributors
# Author: Houqi Zuo <[email protected]>
import os

from avocado.utils import process

from virttest import arch, utils_misc
from virttest.vt_utils.net import interface as iface


def create_macvtap(iface=None, tapname=None, mode="vepa", mac_addr=None):
"""
Create a Macvtap device.

:param iface: The physical interface.
:type iface: String.
:param tapname: The macvtap name.
:type tapname: String.
:param mode: The macvtap type mode (vepa, bridge, private)
:type mode: String.
:param mac_addr: The macvtap mac address.
:type mac_addr: String.

:raise: A RuntimeError may be raised if running command fails.
"""
if not iface:
iface = get_macvtap_base_iface(iface)
if not tapname:
tapname = "macvtap" + utils_misc.generate_random_id()
cmd = "ip link add link %s name %s type %s" % (iface, tapname, mode)
process.run(cmd, shell=True)
if mac_addr:
cmd = "ip link set %s address %s up" % (tapname, mac_addr)
process.run(cmd, shell=True)


def show_macvtap(tapname):
"""
Show the macvtap details.

:param tapname: The macvtap name.
:type tapname: String.

:return: The macvtap details.
:rtype: String.
"""
cmd = "ip link show %s" % tapname
cmd_obj = process.run(cmd, shell=True)
return cmd_obj.stdout_text.strip()


def delete_macvtap(tapname):
"""
Delete the macvtap.

:param tapname: The macvtap name.
:type tapname: String.
"""
cmd = "ip link delete %s" % tapname
process.run(cmd, shell=True)


def get_macvtap_base_iface(base_interface=None):
"""
Get physical interface to create macvtap, if you assigned base interface
is valid(not belong to any bridge and is up), will use it; else use the
first physical interface, which is not a brport and up.
"""
tap_base_device = None

(dev_int, _) = iface.get_sorted_net_if()

if base_interface and base_interface in dev_int:
if (not iface.net_if_is_brport(base_interface)) and (
iface.is_iface_flag_same(base_interface, arch.IFF_UP)
):
tap_base_device = base_interface

if not tap_base_device:
for interface in dev_int:
if iface.net_if_is_brport(interface):
continue
if iface.is_iface_flag_same(interface, arch.IFF_UP):
tap_base_device = interface
break

return tap_base_device


def open_macvtap(macvtap, queues=1):
"""
Open a macvtap device and returns its file descriptors which are used by
fds=<fd1:fd2:..> parameter of qemu.

For single queue, only returns one file descriptor, it's used by
fd=<fd> legacy parameter of qemu.

If you not have a switch support vepa in you env, run this type case you
need at least two nic on you host [just workaround].

:param macvtap: The macvtap name.
:type macvtap: String.
:param queues: Queue number.
:type queues: Integer.

:return: The file descriptors which are used
by fds=<fd1:fd2:..> parameter of qemu.
:rtype: String.
"""
tapfds = []
macvtap = "/dev/%s" % macvtap
for queue in range(int(queues)):
tapfds.append(str(os.open(macvtap, os.O_RDWR)))
return ":".join(tapfds)
61 changes: 61 additions & 0 deletions virttest/vt_utils/net/drivers/ovs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Library for the openvswitch related functions.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat (c) 2024 and Avocado contributors
# Author: Houqi Zuo <[email protected]>
from avocado.utils import process


def ovs_br_exists(brname):
"""
Check if bridge exists or not.

:param brname: Name of the bridge.
:type brname: String.

:return: True if found, otherwise, return False.
:rtype: Boolean.

:raise: RuntimeError if executing command fails.
"""
cmd = "ovs-vsctl br-exists %s" % brname
cmd_obj = process.run(cmd, shell=True)
status = cmd_obj.exit_status
if status != 0:
return False
return True


def add_ovs_bridge(brname):
"""
Add a bridge.

:param brname: Name of the bridge.
:type brname: String.

:raise: RuntimeError if executing command fails.
"""
cmd = "ovs-vsctl --may-exist add-br %s" % brname
process.run(cmd, shell=True)


def del_ovs_bridge(brname):
"""
Delete a bridge from ovs.

:param brname: Name of the bridge.
:type brname: String.

:raise: RuntimeError if executing command fails.
"""
cmd = "ovs-vsctl --if-exists del-br %s" % brname
process.run(cmd, shell=True)
Loading
Loading