diff --git a/etc/os-net-config/samples/ovs_dpdk_bond.json b/etc/os-net-config/samples/ovs_dpdk_bond.json index a921d605..410d4594 100644 --- a/etc/os-net-config/samples/ovs_dpdk_bond.json +++ b/etc/os-net-config/samples/ovs_dpdk_bond.json @@ -7,6 +7,7 @@ "type" : "ovs_dpdk_bond", "name" : "dpdkbond0", "mtu" : 9000, + "rx_queue": 4, "members": [ { "type" : "ovs_dpdk_port", diff --git a/etc/os-net-config/samples/ovs_dpdk_bond.yaml b/etc/os-net-config/samples/ovs_dpdk_bond.yaml index 3fc9f7d3..17a73a3f 100644 --- a/etc/os-net-config/samples/ovs_dpdk_bond.yaml +++ b/etc/os-net-config/samples/ovs_dpdk_bond.yaml @@ -15,6 +15,14 @@ network_config: name: dpdkbond0 # MTU is optional, e.g. for jumbo frames mtu: 9000 + # rx_queue is optional, used for multi-queue option. It configures the + # maximum number of queues for each interface associated with the + # ovs_dpdk_bond. If not defined, the physical interfaces will have + # single queue. + # (rx_queue) x (Number of members in the ovs_dpdk_bond) should be less + # than the number of PMD cores, as each queue will have one PMD thread + # (CPU) associated with it. + rx_queue: 4 members: - type: ovs_dpdk_port diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index d98df314..997b6954 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -326,6 +326,11 @@ class IfcfgNetConfig(os_net_config.NetConfig): for member in base_opt.members: ovs_extra.append("set Interface %s mtu_request=$MTU" % member.name) + if base_opt.rx_queue: + data += "RX_QUEUE=%i\n" % base_opt.rx_queue + for member in base_opt.members: + ovs_extra.append("set Interface %s options:n_rxq=" + "$RX_QUEUE" % member.name) if base_opt.ovs_options: data += "OVS_OPTIONS=\"%s\"\n" % base_opt.ovs_options ovs_extra.extend(base_opt.ovs_extra) diff --git a/os_net_config/objects.py b/os_net_config/objects.py index 86e08956..5fe6e49d 100644 --- a/os_net_config/objects.py +++ b/os_net_config/objects.py @@ -1057,7 +1057,7 @@ class OvsDpdkBond(_BaseOpts): routes=None, mtu=None, primary=False, members=None, ovs_options=None, ovs_extra=None, nic_mapping=None, persist_mapping=False, defroute=True, dhclient_args=None, - dns_servers=None, nm_controlled=False): + dns_servers=None, nm_controlled=False, rx_queue=None): super(OvsDpdkBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses, routes, mtu, primary, nic_mapping, persist_mapping, @@ -1066,6 +1066,7 @@ class OvsDpdkBond(_BaseOpts): self.members = members or [] self.ovs_options = ovs_options self.ovs_extra = format_ovs_extra(self, ovs_extra) + self.rx_queue = rx_queue for member in self.members: if member.primary: @@ -1088,6 +1089,7 @@ class OvsDpdkBond(_BaseOpts): persist_mapping, defroute, dhclient_args, dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json( json, include_primary=False) + rx_queue = json.get('rx_queue', None) ovs_options = json.get('ovs_options') ovs_extra = json.get('ovs_extra', []) if not isinstance(ovs_extra, list): @@ -1119,7 +1121,7 @@ class OvsDpdkBond(_BaseOpts): persist_mapping=persist_mapping, defroute=defroute, dhclient_args=dhclient_args, dns_servers=dns_servers, - nm_controlled=nm_controlled) + nm_controlled=nm_controlled, rx_queue=rx_queue) class VppInterface(_BaseOpts): diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py index c67115bd..80f83f1b 100644 --- a/os_net_config/tests/test_impl_ifcfg.py +++ b/os_net_config/tests/test_impl_ifcfg.py @@ -1031,6 +1031,85 @@ BOND_IFACES="dpdk0 dpdk1" MTU=9000 OVS_EXTRA="set Interface dpdk0 mtu_request=$MTU \ -- set Interface dpdk1 mtu_request=$MTU" +""" + self.assertEqual(dpdk_bond_config, + self.get_interface_config('dpdkbond0')) + + def test_network_ovs_dpdk_bond_with_rx_queue(self): + nic_mapping = {'nic1': 'eth0', 'nic2': 'eth1', 'nic3': 'eth2'} + self.stubbed_mapped_nics = nic_mapping + + iface0 = objects.Interface(name='nic2') + dpdk0 = objects.OvsDpdkPort(name='dpdk0', members=[iface0]) + iface1 = objects.Interface(name='nic3') + dpdk1 = objects.OvsDpdkPort(name='dpdk1', members=[iface1]) + bond = objects.OvsDpdkBond('dpdkbond0', rx_queue=4, + members=[dpdk0, dpdk1]) + bridge = objects.OvsUserBridge('br-link', members=[bond]) + + def test_bind_dpdk_interfaces(ifname, driver, noop): + self.assertIn(ifname, ['eth1', 'eth2']) + self.assertEqual(driver, 'vfio-pci') + self.stubs.Set(utils, 'bind_dpdk_interfaces', + test_bind_dpdk_interfaces) + + self.provider.add_ovs_dpdk_bond(bond) + self.provider.add_ovs_user_bridge(bridge) + + dpdk_bond_config = """# This file is autogenerated by os-net-config +DEVICE=dpdkbond0 +ONBOOT=yes +HOTPLUG=no +NM_CONTROLLED=no +PEERDNS=no +DEVICETYPE=ovs +TYPE=OVSDPDKBond +OVS_BRIDGE=br-link +BOND_IFACES="dpdk0 dpdk1" +RX_QUEUE=4 +OVS_EXTRA="set Interface dpdk0 options:n_rxq=$RX_QUEUE \ +-- set Interface dpdk1 options:n_rxq=$RX_QUEUE" +""" + self.assertEqual(dpdk_bond_config, + self.get_interface_config('dpdkbond0')) + + def test_network_ovs_dpdk_bond_with_mtu_and_rx_queue(self): + nic_mapping = {'nic1': 'eth0', 'nic2': 'eth1', 'nic3': 'eth2'} + self.stubbed_mapped_nics = nic_mapping + + iface0 = objects.Interface(name='nic2') + dpdk0 = objects.OvsDpdkPort(name='dpdk0', members=[iface0]) + iface1 = objects.Interface(name='nic3') + dpdk1 = objects.OvsDpdkPort(name='dpdk1', members=[iface1]) + bond = objects.OvsDpdkBond('dpdkbond0', rx_queue=4, mtu=9000, + members=[dpdk0, dpdk1]) + bridge = objects.OvsUserBridge('br-link', members=[bond]) + + def test_bind_dpdk_interfaces(ifname, driver, noop): + self.assertIn(ifname, ['eth1', 'eth2']) + self.assertEqual(driver, 'vfio-pci') + self.stubs.Set(utils, 'bind_dpdk_interfaces', + test_bind_dpdk_interfaces) + + self.provider.add_ovs_dpdk_bond(bond) + self.provider.add_ovs_user_bridge(bridge) + + dpdk_bond_config = """# This file is autogenerated by os-net-config +DEVICE=dpdkbond0 +ONBOOT=yes +HOTPLUG=no +NM_CONTROLLED=no +PEERDNS=no +DEVICETYPE=ovs +TYPE=OVSDPDKBond +OVS_BRIDGE=br-link +BOND_IFACES="dpdk0 dpdk1" +RX_QUEUE=4 +MTU=9000 +OVS_EXTRA="set Interface dpdk0 mtu_request=$MTU \ +-- set Interface dpdk1 mtu_request=$MTU \ +-- set Interface dpdk0 options:n_rxq=$RX_QUEUE \ +-- set Interface dpdk1 options:n_rxq=$RX_QUEUE" """ self.assertEqual(dpdk_bond_config, self.get_interface_config('dpdkbond0'))