diff --git a/SOURCES/tuned-2.15.0-netdev-queue-count.patch b/SOURCES/tuned-2.15.0-netdev-queue-count.patch
new file mode 100644
index 0000000..09e31d7
--- /dev/null
+++ b/SOURCES/tuned-2.15.0-netdev-queue-count.patch
@@ -0,0 +1,168 @@
+diff --git a/profiles/realtime/realtime-variables.conf b/profiles/realtime/realtime-variables.conf
+index c2da595..9d929e0 100644
+--- a/profiles/realtime/realtime-variables.conf
++++ b/profiles/realtime/realtime-variables.conf
+@@ -9,3 +9,11 @@
+ # kernel supports it.
+ #
+ # isolate_managed_irq=Y
++#
++#
++# Set the desired combined queue count value using the parameter provided
++# below. Ideally this should be set to the number of housekeeping CPUs i.e.,
++# in the example given below it is assumed that the system has 4 housekeeping
++# (non-isolated) CPUs.
++#
++# netdev_queue_count=4
+diff --git a/profiles/realtime/tuned.conf b/profiles/realtime/tuned.conf
+index 8eed36e..2400849 100644
+--- a/profiles/realtime/tuned.conf
++++ b/profiles/realtime/tuned.conf
+@@ -35,6 +35,9 @@ assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_exp
+ isolate_managed_irq = ${isolate_managed_irq}
+ managed_irq=${f:regex_search_ternary:${isolate_managed_irq}:\b[y,Y,1,t,T]\b:managed_irq,domain,:}
+ 
++[net]
++channels=combined ${f:check_net_queue_count:${netdev_queue_count}}
++
+ [sysctl]
+ kernel.hung_task_timeout_secs = 600
+ kernel.nmi_watchdog = 0
+diff --git a/tuned/profiles/functions/function_check_net_queue_count.py b/tuned/profiles/functions/function_check_net_queue_count.py
+new file mode 100644
+index 0000000..eb54f98
+--- /dev/null
++++ b/tuned/profiles/functions/function_check_net_queue_count.py
+@@ -0,0 +1,22 @@
++import tuned.logs
++from . import base
++
++log = tuned.logs.get()
++
++class check_net_queue_count(base.Function):
++	"""
++	Checks whether the user has specified a queue count for net devices. If
++        not, return the number of housekeeping CPUs.
++	"""
++	def __init__(self):
++		# 1 argument
++		super(check_net_queue_count, self).__init__("check_net_queue_count", 1, 1)
++
++	def execute(self, args):
++		if not super(check_net_queue_count, self).execute(args):
++			return None
++		if args[0].isdigit():
++			return args[0]
++		(ret, out) = self._cmd.execute(["nproc"])
++		log.warn("net-dev queue count is not correctly specified, setting it to HK CPUs %s" % (out))
++		return out
+diff --git a/tuned/plugins/plugin_net.py b/tuned/plugins/plugin_net.py
+index 4d4c19e..a20d87e 100644
+--- a/tuned/plugins/plugin_net.py
++++ b/tuned/plugins/plugin_net.py
+@@ -122,6 +122,13 @@ class NetTuningPlugin(base.Plugin):
+ 			"rx-jumbo": None,
+ 			"tx": None }
+ 
++	@classmethod
++	def _get_config_options_channels(cls):
++		return { "rx": None,
++			"tx": None,
++			"other": None,
++			"combined": None }
++
+ 	@classmethod
+ 	def _get_config_options(cls):
+ 		return {
+@@ -132,6 +139,7 @@ class NetTuningPlugin(base.Plugin):
+ 			"coalesce": None,
+ 			"pause": None,
+ 			"ring": None,
++			"channels": None,
+ 		}
+ 
+ 	def _init_stats_and_idle(self, instance, device):
+@@ -282,7 +290,8 @@ class NetTuningPlugin(base.Plugin):
+ 		params = set(d.keys())
+ 		supported_getter = { "coalesce": self._get_config_options_coalesce, \
+ 				"pause": self._get_config_options_pause, \
+-				"ring": self._get_config_options_ring }
++				"ring": self._get_config_options_ring, \
++				"channels": self._get_config_options_channels }
+ 		supported = set(supported_getter[context]().keys())
+ 		if not params.issubset(supported):
+ 			log.error("unknown %s parameter(s): %s" % (context, str(params - supported)))
+@@ -313,6 +322,29 @@ class NetTuningPlugin(base.Plugin):
+ 		l = [x for x in [re.split(r":\s*", x) for x in l] if len(x) == 2]
+ 		return dict(l)
+ 
++	# parse output of ethtool -l
++	def _parse_channels_parameters(self, s):
++		a = re.split(r"^Current hardware settings:$", s, flags=re.MULTILINE)
++		s = a[1]
++		s = self._cmd.multiple_re_replace(\
++				{"RX": "rx",
++				"TX": "tx",
++				"Other": "other",
++				"Combined": "combined"}, s)
++		l = s.split("\n")
++		l = [x for x in l if x != '']
++		l = [x for x in [re.split(r":\s*", x) for x in l] if len(x) == 2]
++		return dict(l)
++
++	def _replace_channels_parameters(self, context, params_list, dev_params):
++		mod_params_list = []
++		if "combined" in params_list:
++			mod_params_list.extend(["rx", params_list[1], "tx", params_list[1]])
++		else:
++			cnt = str(max(int(params_list[1]), int(params_list[3])))
++			mod_params_list.extend(["combined", cnt])
++		return dict(list(zip(mod_params_list[::2], mod_params_list[1::2])))
++
+ 	def _check_device_support(self, context, parameters, device, dev_params):
+ 		"""Filter unsupported parameters and log warnings about it
+ 
+@@ -337,7 +369,8 @@ class NetTuningPlugin(base.Plugin):
+ 			parameters.pop(param, None)
+ 
+ 	def _get_device_parameters(self, context, device):
+-		context2opt = { "coalesce": "-c", "features": "-k", "pause": "-a", "ring": "-g" }
++		context2opt = { "coalesce": "-c", "features": "-k", "pause": "-a", "ring": "-g", \
++				"channels": "-l"}
+ 		opt = context2opt[context]
+ 		ret, value = self._cmd.execute(["ethtool", opt, device])
+ 		if ret != 0 or len(value) == 0:
+@@ -345,7 +378,8 @@ class NetTuningPlugin(base.Plugin):
+ 		context2parser = { "coalesce": self._parse_device_parameters, \
+ 				"features": self._parse_device_parameters, \
+ 				"pause": self._parse_pause_parameters, \
+-				"ring": self._parse_ring_parameters }
++				"ring": self._parse_ring_parameters, \
++				"channels": self._parse_channels_parameters }
+ 		parser = context2parser[context]
+ 		d = parser(value)
+ 		if context == "coalesce" and not self._check_parameters(context, d):
+@@ -362,10 +396,14 @@ class NetTuningPlugin(base.Plugin):
+ 		# check if device supports parameters and filter out unsupported ones
+ 		if dev_params:
+ 			self._check_device_support(context, d, device, dev_params)
++			# replace the channel parameters based on the device support
++			if context == "channels" and int(dev_params[next(iter(d))]) == 0:
++				d = self._replace_channels_parameters(context, self._cmd.dict2list(d), dev_params)
+ 
+ 		if not sim and len(d) != 0:
+ 			log.debug("setting %s: %s" % (context, str(d)))
+-			context2opt = { "coalesce": "-C", "features": "-K", "pause": "-A", "ring": "-G" }
++			context2opt = { "coalesce": "-C", "features": "-K", "pause": "-A", "ring": "-G", \
++                                "channels": "-L"}
+ 			opt = context2opt[context]
+ 			# ignore ethtool return code 80, it means parameter is already set
+ 			self._cmd.execute(["ethtool", opt, device] + self._cmd.dict2list(d), no_errors = [80])
+@@ -422,3 +460,7 @@ class NetTuningPlugin(base.Plugin):
+ 	@command_custom("ring", per_device = True)
+ 	def _ring(self, start, value, device, verify, ignore_missing):
+ 		return self._custom_parameters("ring", start, value, device, verify)
++
++	@command_custom("channels", per_device = True)
++	def _channels(self, start, value, device, verify, ignore_missing):
++		return self._custom_parameters("channels", start, value, device, verify)
diff --git a/SPECS/tuned.spec b/SPECS/tuned.spec
index 7dbef38..3543252 100644
--- a/SPECS/tuned.spec
+++ b/SPECS/tuned.spec
@@ -34,7 +34,7 @@
 Summary: A dynamic adaptive system tuning daemon
 Name: tuned
 Version: 2.15.0
-Release: 1%{?prerel1}%{?dist}
+Release: 2%{?prerel1}%{?dist}
 License: GPLv2+
 Source0: https://github.com/redhat-performance/%{name}/archive/v%{version}%{?prerel2}/%{name}-%{version}%{?prerel2}.tar.gz
 # RHEL-8 specific recommend.conf:
@@ -75,6 +75,7 @@ Recommends: kmod
 %if 0%{?rhel} > 7
 Requires: python3-syspurpose
 %endif
+Patch0: tuned-2.15.0-netdev-queue-count.patch
 
 %description
 The tuned package contains a daemon that tunes system settings dynamically.
@@ -229,6 +230,7 @@ Additional tuned profile(s) targeted to PostgreSQL server loads.
 
 %prep
 %setup -q -n %{name}-%{version}%{?prerel2}
+%patch0 -p1
 
 # Replace the upstream recommend.conf with a RHEL-8-specific one
 rm -f recommend.conf
@@ -510,6 +512,10 @@ fi
 %{_mandir}/man7/tuned-profiles-postgresql.7*
 
 %changelog
+* Fri Feb 19 2021 Jaroslav Škarvada <jskarvad@redhat.com> - 2.15.0-2
+- realtime: added support for netdev_queue_count and extended plugin_net
+  resolves: rhbz#1846767
+
 * Thu Dec 17 2020 Jaroslav Škarvada <jskarvad@redhat.com> - 2.15.0-1
 - new release
   - rebased tuned to latest upstream