mbox series

[net-next,v2,0/3] net: introduce rps_default_mask

Message ID cover.1604055792.git.pabeni@redhat.com
Headers show
Series net: introduce rps_default_mask | expand

Message

Paolo Abeni Oct. 30, 2020, 11:16 a.m. UTC
Real-time setups try hard to ensure proper isolation between time
critical applications and e.g. network processing performed by the
network stack in softirq and RPS is used to move the softirq 
activity away from the isolated core.

If the network configuration is dynamic, with netns and devices
routinely created at run-time, enforcing the correct RPS setting
on each newly created device allowing to transient bad configuration
became complex.

These series try to address the above, introducing a new
sysctl knob: rps_default_mask. The new sysctl entry allows
configuring a systemwide RPS mask, to be enforced since receive 
queue creation time without any fourther per device configuration
required.

Additionally, a simple self-test is introduced to check the 
rps_default_mask behavior.

v1 -> v2:
 - fix sparse warning in patch 2/3

Paolo Abeni (3):
  net/sysctl: factor-out netdev_rx_queue_set_rps_mask() helper
  net/core: introduce default_rps_mask netns attribute
  self-tests: introduce self-tests for RPS default mask

 Documentation/admin-guide/sysctl/net.rst      |  6 ++
 include/linux/netdevice.h                     |  1 +
 net/core/net-sysfs.c                          | 73 +++++++++++--------
 net/core/sysctl_net_core.c                    | 58 +++++++++++++++
 tools/testing/selftests/net/Makefile          |  1 +
 tools/testing/selftests/net/config            |  3 +
 .../testing/selftests/net/rps_default_mask.sh | 57 +++++++++++++++
 7 files changed, 169 insertions(+), 30 deletions(-)
 create mode 100755 tools/testing/selftests/net/rps_default_mask.sh

Comments

Paolo Abeni Nov. 3, 2020, 3:22 p.m. UTC | #1
On Mon, 2020-11-02 at 14:54 -0800, Jakub Kicinski wrote:
> On Fri, 30 Oct 2020 12:16:00 +0100 Paolo Abeni wrote:

> > Real-time setups try hard to ensure proper isolation between time

> > critical applications and e.g. network processing performed by the

> > network stack in softirq and RPS is used to move the softirq 

> > activity away from the isolated core.

> > 

> > If the network configuration is dynamic, with netns and devices

> > routinely created at run-time, enforcing the correct RPS setting

> > on each newly created device allowing to transient bad configuration

> > became complex.

> > 

> > These series try to address the above, introducing a new

> > sysctl knob: rps_default_mask. The new sysctl entry allows

> > configuring a systemwide RPS mask, to be enforced since receive 

> > queue creation time without any fourther per device configuration

> > required.

> > 

> > Additionally, a simple self-test is introduced to check the 

> > rps_default_mask behavior.

> 

> RPS is disabled by default, the processing is going to happen wherever

> the IRQ is mapped, and one would hope that the IRQ is not mapped to the

> core where the critical processing runs.

> 

> Would you mind elaborating further on the use case?


On Mon, 2020-11-02 at 15:27 -0800, Saeed Mahameed wrote:
> The whole thing can be replaced with a user daemon scripts that

> monitors all newly created devices and assign to them whatever rps mask

> (call it default).

> 

> So why do we need this special logic in kernel ? 

> 

> I am not sure about this, but if rps queues sysfs are available before

> the netdev is up, then you can also use udevd to assign the rps masks

> before such devices are even brought up, so you would avoid the race

> conditions that you described, which are not really clear to me to be

> honest.


Thank you for the feedback.

Please allow me to answer you both here, as your questions are related.

The relevant use case is an host running containers (with the related
orchestration tools) in a RT environment. Virtual devices (veths, ovs
ports, etc.) are created by the orchestration tools at run-time.
Critical processes are allowed to send packets/generate outgoing
network traffic - but any interrupt is moved away from the related
cores, so that usual incoming network traffic processing does not
happen there.

Still an xmit operation on a virtual devices may be transmitted via ovs
or veth, with the relevant forwarding operation happening in a softirq
on the same CPU originating the packet. 

RPS is configured (even) on such virtual devices to move away the
forwarding from the relevant CPUs.

As Saeed noted, such configuration could be possibly performed via some
user-space daemon monitoring network devices and network namespaces
creation. That will be anyway prone to some race: the orchestation tool
may create and enable the netns and virtual devices before the daemon
has properly set the RPS mask.

In the latter scenario some packet forwarding could still slip in the
relevant CPU, causing measurable latency. In all non RT scenarios the
above will be likely irrelevant, but in the RT context that is not
acceptable - e.g. it causes in real environments latency above the
defined limits, while the proposed patches avoid the issue.

Do you see any other simple way to avoid the above race?

Please let me know if the above answers your doubts,

Paolo
Marcelo Tosatti Nov. 4, 2020, 6:18 p.m. UTC | #2
On Wed, Nov 04, 2020 at 06:36:08PM +0100, Paolo Abeni wrote:
> On Tue, 2020-11-03 at 08:52 -0800, Jakub Kicinski wrote:

> > On Tue, 03 Nov 2020 16:22:07 +0100 Paolo Abeni wrote:

> > > The relevant use case is an host running containers (with the related

> > > orchestration tools) in a RT environment. Virtual devices (veths, ovs

> > > ports, etc.) are created by the orchestration tools at run-time.

> > > Critical processes are allowed to send packets/generate outgoing

> > > network traffic - but any interrupt is moved away from the related

> > > cores, so that usual incoming network traffic processing does not

> > > happen there.

> > > 

> > > Still an xmit operation on a virtual devices may be transmitted via ovs

> > > or veth, with the relevant forwarding operation happening in a softirq

> > > on the same CPU originating the packet. 

> > > 

> > > RPS is configured (even) on such virtual devices to move away the

> > > forwarding from the relevant CPUs.

> > > 

> > > As Saeed noted, such configuration could be possibly performed via some

> > > user-space daemon monitoring network devices and network namespaces

> > > creation. That will be anyway prone to some race: the orchestation tool

> > > may create and enable the netns and virtual devices before the daemon

> > > has properly set the RPS mask.

> > > 

> > > In the latter scenario some packet forwarding could still slip in the

> > > relevant CPU, causing measurable latency. In all non RT scenarios the

> > > above will be likely irrelevant, but in the RT context that is not

> > > acceptable - e.g. it causes in real environments latency above the

> > > defined limits, while the proposed patches avoid the issue.

> > > 

> > > Do you see any other simple way to avoid the above race?

> > > 

> > > Please let me know if the above answers your doubts,

> > 

> > Thanks, that makes it clearer now.

> > 

> > Depending on how RT-aware your container management is it may or may not

> > be the right place to configure this, as it creates the veth interface.

> > Presumably it's the container management which does the placement of

> > the tasks to cores, why is it not setting other attributes, like RPS?

> 

> The container orchestration is quite complex, and I'm unsure isolation

> and networking configuration are performed (or can be performed) by the

> same precess (without an heavy refactor).


Also for the host side (no containers) the same issue will have to be handled 
for PCI hotplug for example. So this fix  will have to be performed in 
every tool that decides to create a network device (while a kernel
solution is global).

> On the flip hand, the global rps mask knob looked quite

> straightforward to me.

> 

> Possibly I can reduce the amount of new code introduced by this

> patchset removing some code duplication

> between rps_default_mask_sysctl() and flow_limit_cpu_sysctl(). Would

> that make this change more acceptable? Or should I drop this

> altogether?

> 

> > Also I wonder if it would make sense to turn this knob into something

> > more generic. When we arrive at the threaded NAPIs - could it make

> > sense for the threads to inherit your mask as the CPUs they are allowed

> > to run on?

> 

> I personally *think* this would be fine - and good. But isn't a bit

> premature discussing the integration of 2 missing pieces ? :)

> 

> Thanks,

> 

> Paolo


About the potential race:

0) network device creation starts, inherits old default_rps_mask,
network device init sleeps
1) set default_rps_mask (new) 
2) change all devices across all network namespaces (walk /sys)
3) network device init wakes up, new device shows up in /sys/ using old default_rps_mask

Why this can't happen?