diff --git a/lnst/Devices/Device.py b/lnst/Devices/Device.py
index d64be627d..5e05c0084 100644
--- a/lnst/Devices/Device.py
+++ b/lnst/Devices/Device.py
@@ -1167,13 +1167,20 @@ def alt_if_names(self):
             return self._nl_msg.get_attr("IFLA_PROP_LIST").get_attrs("IFLA_ALT_IFNAME")
         except:
             return []
-    
+
     def keep_addrs_on_down(self):
         exec_cmd(f"echo 1 > /proc/sys/net/ipv6/conf/{self.name}/keep_addr_on_down")
 
     def remove_addrs_on_down(self):
         exec_cmd(f"echo 0 > /proc/sys/net/ipv6/conf/{self.name}/keep_addr_on_down")
 
+    # TODO: implement through pyroute once supported
+    def vf_trust(self, vf_index: int, trusted: str):
+        if trusted not in ["on", "off"]:
+            raise DeviceConfigError(f"Incorrect value for vf trust: {trusted}")
+
+        exec_cmd(f"ip link set dev {self.name} vf {vf_index} trust {trusted}")
+
     #TODO implement proper Route objects
     #consider the same as with tc?
     # def route_add(self, dest):
diff --git a/lnst/Recipes/ENRT/BondRecipe.py b/lnst/Recipes/ENRT/BondRecipe.py
index 5e120d4b6..81268e310 100644
--- a/lnst/Recipes/ENRT/BondRecipe.py
+++ b/lnst/Recipes/ENRT/BondRecipe.py
@@ -1,8 +1,6 @@
 from collections.abc import Collection
 from lnst.Common.Parameters import (
     Param,
-    IntParam,
-    StrParam,
     IPv4NetworkParam,
     IPv6NetworkParam,
 )
@@ -18,10 +16,11 @@
     CommonHWSubConfigMixin)
 from lnst.Recipes.ENRT.ConfigMixins.PerfReversibleFlowMixin import (
     PerfReversibleFlowMixin)
+from lnst.Recipes.ENRT.BondingMixin import BondingMixin
 from lnst.RecipeCommon.Ping.PingEndpoints import PingEndpoints
-from lnst.Devices import BondDevice
+from lnst.Devices import RemoteDevice
 
-class BondRecipe(PerfReversibleFlowMixin, CommonHWSubConfigMixin, OffloadSubConfigMixin,
+class BondRecipe(BondingMixin, PerfReversibleFlowMixin, CommonHWSubConfigMixin, OffloadSubConfigMixin,
     BaremetalEnrtRecipe):
     """
     This recipe implements Enrt testing for a network scenario that looks
@@ -43,16 +42,9 @@ class BondRecipe(PerfReversibleFlowMixin, CommonHWSubConfigMixin, OffloadSubConf
         |            host1            |     |      host2     |
         '-----------------------------'     '----------------'
 
-    The recipe provides additional recipe parameters to configure the bonding
+    Refer to :any:`BondingMixin` for parameters to configure the bonding
     device.
 
-        :param bonding_mode:
-            (mandatory test parameter) the bonding mode to be configured on
-            the bond0 device.
-        :param miimon_value:
-            (mandatory test parameter) the miimon interval to be configured
-            on the bond0 device.
-
     All sub configurations are included via Mixin classes.
 
     The actual test machinery is implemented in the :any:`BaseEnrtRecipe` class.
@@ -73,9 +65,6 @@ class BondRecipe(PerfReversibleFlowMixin, CommonHWSubConfigMixin, OffloadSubConf
     net_ipv4 = IPv4NetworkParam(default="192.168.101.0/24")
     net_ipv6 = IPv6NetworkParam(default="fc00::/64")
 
-    bonding_mode = StrParam(mandatory=True)
-    miimon_value = IntParam(mandatory=True)
-
     def test_wide_configuration(self):
         """
         Test wide configuration for this recipe involves creating a bonding
@@ -91,12 +80,14 @@ def test_wide_configuration(self):
         host1, host2 = self.matched.host1, self.matched.host2
         config = super().test_wide_configuration()
 
-        host1.bond0 = BondDevice(mode=self.params.bonding_mode,
-            miimon=self.params.miimon_value)
 
-        for dev in [host1.eth0, host1.eth1]:
-            dev.down()
-            host1.bond0.slave_add(dev)
+        self.create_bond_devices(
+            {
+                "host1": {
+                    "bond0": [host1.eth0, host1.eth1]
+                }
+            }
+        )
 
         ipv4_addr = interface_addresses(self.params.net_ipv4)
         ipv6_addr = interface_addresses(self.params.net_ipv6)
@@ -141,6 +132,12 @@ def generate_test_wide_description(self, config: EnrtConfiguration):
                 host1.bond0.miimon
             )
         ]
+
+        if self.params.bonding_mode in ["active-backup", "1"]:
+            desc += ["Configured {}.{}.fail_over_mac = {}".format(
+                host1.hostid, host1.bond0.name,
+                self.params.fail_over_mac
+            )]
         return desc
 
     def generate_ping_endpoints(self, config):
@@ -245,3 +242,7 @@ def pause_frames_dev_list(self):
         """
         return [self.matched.host1.eth0, self.matched.host1.eth1,
             self.matched.host2.eth0]
+
+    @property
+    def vf_trust_device_list(self) -> list[RemoteDevice]:
+        return [sriov_devices.phys_dev for sriov_devices in self.vf_config[self.matched.host1]]
diff --git a/lnst/Recipes/ENRT/BondingMixin.py b/lnst/Recipes/ENRT/BondingMixin.py
new file mode 100644
index 000000000..2f06386d0
--- /dev/null
+++ b/lnst/Recipes/ENRT/BondingMixin.py
@@ -0,0 +1,70 @@
+from lnst.Common.Parameters import (
+    IntParam,
+    StrParam,
+    ChoiceParam,
+)
+from lnst.Devices import RemoteDevice, BondDevice
+from lnst.Controller.Recipe import RecipeError
+
+
+class BondingMixin:
+    """
+    The recipe mixin provides additional recipe parameters to configure the
+    bonding device.
+
+        :param bonding_mode:
+            (mandatory test parameter) the bonding mode to be configured on
+            the bond0 device.
+        :param miimon_value:
+            (mandatory test parameter) the miimon interval to be configured
+            on the bond0 device.
+        :param fail_over_mac:
+            the fail_over_mac mode to be configured on the bond0 device.
+    """
+    bonding_mode = StrParam(mandatory=True)
+    miimon_value = IntParam(mandatory=True)
+    fail_over_mac = ChoiceParam(
+        StrParam, choices={"none", "active", "follow"}, default="none"
+    )
+
+    def create_bond_devices(
+        self, bond_devices_specs: dict[str: dict[str: list[RemoteDevice]]] = {}
+    ) -> None:
+        """
+        The derived class should call:
+        ```
+        self.create_bond_devices(
+            {
+                "host1": {
+                    "bond0": [host1.nic1, host1.nic2]
+                },
+                "host2": {
+                    "bond0": [host2.nic1, host2.nic2]
+                }
+            }
+
+        That would create devices accessible by host1.bond0 and host2.bond0
+        )
+        ```
+        """
+        device_params = dict(
+            mode=self.params.bonding_mode,
+            miimon=self.params.miimon_value,
+        )
+
+        if self.params.bonding_mode in ["active-backup", "1"]:
+            device_params["fail_over_mac"] = self.params.fail_over_mac
+
+        for host_str, spec in bond_devices_specs.items():
+            for bond_dev_name, bonded_devices in spec.items():
+                if len({dev.host for dev in bonded_devices}) > 1:
+                    raise RecipeError(
+                        f"Cannot create bond device with ports coming from different hosts, {bonded_devices}"
+                    )
+
+                host = getattr(self.matched, host_str)
+                setattr(host, bond_dev_name, BondDevice(**device_params))
+                bond_device = getattr(host, bond_dev_name)
+                for dev in bonded_devices:
+                    dev.down()
+                    bond_device.slave_add(dev)
diff --git a/lnst/Recipes/ENRT/DoubleBondRecipe.py b/lnst/Recipes/ENRT/DoubleBondRecipe.py
index 3a74a7408..cdd72b2db 100644
--- a/lnst/Recipes/ENRT/DoubleBondRecipe.py
+++ b/lnst/Recipes/ENRT/DoubleBondRecipe.py
@@ -1,8 +1,6 @@
 from collections.abc import Collection
 from lnst.Common.Parameters import (
     Param,
-    IntParam,
-    StrParam,
     IPv4NetworkParam,
     IPv6NetworkParam,
 )
@@ -16,11 +14,39 @@
     OffloadSubConfigMixin)
 from lnst.Recipes.ENRT.ConfigMixins.CommonHWSubConfigMixin import (
     CommonHWSubConfigMixin)
+from lnst.Recipes.ENRT.BondingMixin import BondingMixin
 from lnst.RecipeCommon.Ping.PingEndpoints import PingEndpoints
-from lnst.Devices import BondDevice
+from lnst.Devices import RemoteDevice
 
-class DoubleBondRecipe(CommonHWSubConfigMixin, OffloadSubConfigMixin,
+class DoubleBondRecipe(BondingMixin, CommonHWSubConfigMixin, OffloadSubConfigMixin,
     BaremetalEnrtRecipe):
+    """
+    This recipe implements Enrt testing for a network scenario that looks
+    as follows
+
+    .. code-block:: none
+
+                                    .--------.
+                   .----------------+        +------------------.
+                   |        .-------+ switch +---------.        |
+                   |        |       '--------'         |        |
+             .-------------------.               .-------------------.
+             |     | bond0  |    |               |     | bond0  |    |
+             | .---'--. .---'--. |               | .---'--. .---'--. |
+        .----|-| eth0 |-| eth1 |-|----.     .----|-| eth0 |-| eth1 |-|----.
+        |    | '------' '------' |    |     |    | '------' '------' |    |
+        |    '-------------------'    |     |    '-------------------'    |
+        |                             |     |                             |
+        |            host1            |     |            host2            |
+        '-----------------------------'     '-----------------------------'
+
+    Refer to :any:`BondingMixin` for parameters to configure the bonding
+    device.
+
+    All sub configurations are included via Mixin classes.
+
+    The actual test machinery is implemented in the :any:`BaseEnrtRecipe` class.
+    """
     host1 = HostReq()
     host1.eth0 = DeviceReq(label="net1", driver=RecipeParam("driver"))
     host1.eth1 = DeviceReq(label="net1", driver=RecipeParam("driver"))
@@ -38,21 +64,25 @@ class DoubleBondRecipe(CommonHWSubConfigMixin, OffloadSubConfigMixin,
     net_ipv4 = IPv4NetworkParam(default="192.168.101.0/24")
     net_ipv6 = IPv6NetworkParam(default="fc00::/64")
 
-    bonding_mode = StrParam(mandatory=True)
-    miimon_value = IntParam(mandatory=True)
-
     def test_wide_configuration(self):
         host1, host2 = self.matched.host1, self.matched.host2
         config = super().test_wide_configuration()
 
         ipv4_addr = interface_addresses(self.params.net_ipv4)
         ipv6_addr = interface_addresses(self.params.net_ipv6)
+
+        self.create_bond_devices(
+            {
+                "host1": {
+                    "bond0": [host1.eth0, host1.eth1]
+                },
+                "host2": {
+                    "bond0": [host2.eth0, host2.eth1]
+                }
+            }
+        )
+
         for host in [host1, host2]:
-            host.bond0 = BondDevice(mode=self.params.bonding_mode,
-                miimon=self.params.miimon_value)
-            for dev in [host.eth0, host.eth1]:
-                dev.down()
-                host.bond0.slave_add(dev)
             config.configure_and_track_ip(host.bond0, next(ipv4_addr))
             config.configure_and_track_ip(host.bond0, next(ipv6_addr))
             for dev in [host.eth0, host.eth1, host.bond0]:
@@ -63,7 +93,6 @@ def test_wide_configuration(self):
         return config
 
     def generate_test_wide_description(self, config: EnrtConfiguration):
-        host1, host2 = self.matched.host1, self.matched.host2
         desc = super().generate_test_wide_description(config)
         desc += [
             "\n".join([
@@ -93,6 +122,16 @@ def generate_test_wide_description(self, config: EnrtConfiguration):
                 for dev in config.configured_devices
             ])
         ]
+        desc.extend([
+            "\n".join([
+                "Configured {}.{}.fail_over_mac = {}".format(
+                    dev.host.hostid, dev.name, dev.fail_over_mac
+                )
+                for dev in config.configured_devices
+            ])
+            if self.params.bonding_mode in ["active-backup", "1"] else []
+        ])
+
         return desc
 
     def generate_ping_endpoints(self, config):
@@ -118,3 +157,7 @@ def dev_interrupt_hw_config_dev_list(self):
     def parallel_stream_qdisc_hw_config_dev_list(self):
         host1, host2 = self.matched.host1, self.matched.host2
         return [host1.eth0, host1.eth1, host2.eth0, host2.eth1]
+
+    @property
+    def vf_trust_device_list(self) -> list[RemoteDevice]:
+        return [sriov_devices.phys_dev for sriov_devices_list in self.vf_config.values() for sriov_devices in sriov_devices_list]
diff --git a/lnst/Recipes/ENRT/UseVfsMixin.py b/lnst/Recipes/ENRT/UseVfsMixin.py
index 5fd5ea450..41db9da80 100644
--- a/lnst/Recipes/ENRT/UseVfsMixin.py
+++ b/lnst/Recipes/ENRT/UseVfsMixin.py
@@ -1,6 +1,7 @@
-from lnst.Common.Parameters import BoolParam
+from lnst.Common.Parameters import BoolParam, ChoiceParam
 from lnst.Controller.Requirements import DeviceReq
 from lnst.Recipes.ENRT.SRIOVDevices import SRIOVDevices
+from lnst.Devices import RemoteDevice
 
 
 class UseVfsMixin:
@@ -12,11 +13,16 @@ class UseVfsMixin:
     with VF Device instances. This allows user to interact with the network
     interfaces without additional changes to the code of recipe.
 
+    Mixin provides two parameters:
+    * use_vfs - main boolean parameter to enable or disable (default) use of VFs
+    * vf_trust - (optional) set the trust parameter of the used VFs, 'on' or 'off'
+
     There are some limitations, for example pause frames cannot be configured
     since the VF do not support these.
     """
 
     use_vfs = BoolParam(default=False)
+    vf_trust = ChoiceParam(choices={'on', 'off'})
 
     def test_wide_configuration(self):
         config = super().test_wide_configuration()
@@ -24,7 +30,7 @@ def test_wide_configuration(self):
         if not self.params.use_vfs:
             return config
 
-        config.vf_config = {}
+        self.vf_config = {}
         for host_key, host_req in self.req:
             dev_names = [key for key, value in host_req if isinstance(value, DeviceReq)]
             host = getattr(self.matched, host_key)
@@ -33,17 +39,22 @@ def test_wide_configuration(self):
             for dev_name in dev_names:
                 dev = getattr(host, dev_name)
                 sriov_devices = SRIOVDevices(dev, 1)
+
                 vf_dev = sriov_devices.vfs[0]
                 host.map_device(dev_name, {"ifname": vf_dev.name})
 
-                host_config = config.vf_config.setdefault(host, [])
+                host_config = self.vf_config.setdefault(host, [])
                 host_config.append(sriov_devices)
 
+        if self.params.get("vf_trust"):
+            for dev in self.vf_trust_device_list:
+                dev.vf_trust(0, self.params.vf_trust)
+
         return config
 
     def test_wide_deconfiguration(self, config):
         if self.params.use_vfs:
-            for host, sriov_devices_list in config.vf_config.items():
+            for host, sriov_devices_list in self.vf_config.items():
                 for sriov_devices in sriov_devices_list:
                     vf_dev = sriov_devices.vfs[0]
                     host.map_device(vf_dev._id, {"ifname": sriov_devices.phys_dev.name})
@@ -56,10 +67,14 @@ def generate_test_wide_description(self, config):
 
         if self.params.use_vfs:
             description += [
-                f"Using vf device {vf_dev.name} of pf {sriov_devices.phys_dev.name} for DeviceReq {host.hostid}.{vf_dev._id}"
-                for host, sriov_devices_list in config.vf_config.items()
+                f"Using vf device {vf_dev.name} of pf {sriov_devices.phys_dev.name} for DeviceReq {host.hostid}.{vf_dev._id}" + (f" trusted={self.params.vf_trust}" if self.params.get("vf_trust") and sriov_devices.phys_dev in self.vf_trust_device_list else "")
+                for host, sriov_devices_list in self.vf_config.items()
                 for sriov_devices in sriov_devices_list
                 for vf_dev in sriov_devices.vfs
             ]
 
         return description
+
+    @property
+    def vf_trust_device_list(self) -> list[RemoteDevice]:
+        return []
diff --git a/lnst/Recipes/ENRT/VlansOverBondRecipe.py b/lnst/Recipes/ENRT/VlansOverBondRecipe.py
index 3ae680a6f..c0242a76e 100644
--- a/lnst/Recipes/ENRT/VlansOverBondRecipe.py
+++ b/lnst/Recipes/ENRT/VlansOverBondRecipe.py
@@ -2,7 +2,6 @@
 from lnst.Common.Parameters import (
     Param,
     IntParam,
-    StrParam,
     IPv4NetworkParam,
     IPv6NetworkParam,
 )
@@ -18,13 +17,14 @@
     CommonHWSubConfigMixin)
 from lnst.Recipes.ENRT.ConfigMixins.PerfReversibleFlowMixin import (
     PerfReversibleFlowMixin)
+from lnst.Recipes.ENRT.BondingMixin import BondingMixin
 from lnst.Devices import VlanDevice
 from lnst.Devices.VlanDevice import VlanDevice as Vlan
-from lnst.Devices import BondDevice
+from lnst.Devices import RemoteDevice
 from lnst.Recipes.ENRT.PingMixins import VlanPingEvaluatorMixin
 from lnst.RecipeCommon.Ping.PingEndpoints import PingEndpoints
 
-class VlansOverBondRecipe(PerfReversibleFlowMixin, VlanPingEvaluatorMixin,
+class VlansOverBondRecipe(BondingMixin, PerfReversibleFlowMixin, VlanPingEvaluatorMixin,
     CommonHWSubConfigMixin, OffloadSubConfigMixin,
     BaremetalEnrtRecipe):
     r"""
@@ -50,16 +50,9 @@ class VlansOverBondRecipe(PerfReversibleFlowMixin, VlanPingEvaluatorMixin,
         |          host1         |   |        host2        |
         '------------------------'   '---------------------'
 
-    The recipe provides additional recipe parameters to configure the bonding
+    Refer to :any:`BondingMixin` for parameters to configure the bonding
     device.
 
-    :param bonding_mode:
-        (mandatory test parameter) the bonding mode to be configured on
-        the bond0 device
-    :param miimon_value:
-        (mandatory test parameter) the miimon interval to be configured
-        on the bond0 device
-
     All sub configurations are included via Mixin classes.
 
     The actual test machinery is implemented in the :any:`BaseEnrtRecipe` class.
@@ -90,9 +83,6 @@ class VlansOverBondRecipe(PerfReversibleFlowMixin, VlanPingEvaluatorMixin,
     vlan2_ipv4 = IPv4NetworkParam(default="192.168.30.0/24")
     vlan2_ipv6 = IPv6NetworkParam(default="fc00:0:0:3::/64")
 
-    bonding_mode = StrParam(mandatory=True)
-    miimon_value = IntParam(mandatory=True)
-
     def test_wide_configuration(self):
         """
         Test wide configuration for this recipe involves creating one bonding
@@ -117,11 +107,14 @@ def test_wide_configuration(self):
         host1, host2 = self.matched.host1, self.matched.host2
         config = super().test_wide_configuration()
 
-        host1.bond0 = BondDevice(mode=self.params.bonding_mode,
-            miimon=self.params.miimon_value)
-        for dev in [host1.eth0, host1.eth1]:
-            dev.down()
-            host1.bond0.slave_add(dev)
+        self.create_bond_devices(
+            {
+                "host1":
+                {
+                    "bond0": [host1.eth0, host1.eth1]
+                }
+            }
+        )
 
         host1.vlan0 = VlanDevice(realdev=host1.bond0, vlan_id=self.params.vlan0_id)
         host1.vlan1 = VlanDevice(realdev=host1.bond0, vlan_id=self.params.vlan1_id)
@@ -200,6 +193,12 @@ def generate_test_wide_description(self, config: EnrtConfiguration):
                 host1.bond0.miimon
             )
         ]
+
+        if self.params.bonding_mode in ["active-backup", "1"]:
+            desc += ["Configured {}.{}.fail_over_mac = {}".format(
+                host1.hostid, host1.bond0.name,
+                host1.bond0.fail_over_mac
+            )]
         return desc
 
     def generate_ping_endpoints(self, config):
@@ -309,3 +308,7 @@ def pause_frames_dev_list(self):
         """
         host1, host2 = self.matched.host1, self.matched.host2
         return [host1.eth0, host1.eth1, host2.eth0]
+
+    @property
+    def vf_trust_device_list(self) -> list[RemoteDevice]:
+        return [sriov_devices.phys_dev for sriov_devices in self.vf_config[self.matched.host1]]