configure_nic_irq_affinity: replace oneshot with monitor daemon#984
configure_nic_irq_affinity: replace oneshot with monitor daemon#984insatomcat wants to merge 1 commit into
Conversation
|
I don't like this solution. Running a script every second to handle IRQs affinity will absolutely create hazardous RT problems The script indeed conflicts with irqbalance, but Tuned documentation explicitly tell to disable the irqbalance service so it should not run on SEAPATH. That said, it is true that the current service doesn't account for modprobe or for specific kernel events. But this shouldn't happen. I would advise you to
|
|
After consideration, I would even advise to remove irqbalance from SEAPATH images entirely |
|
Thanks for the review. I think there's a misunderstanding on the "every second" part. The daemon does not poll every second. The only "1s" in the PR is On irqbalance: fully agreed. We're disabling it (and removing it from the images) in #985, so that conflict goes away as you suggest — it's already planned. On the kernel params: The core reason for the change is problem #1, and it's not an edge case: |
|
Indeed, I missunderstood the Restart=always config. I understand the problem now. Out of curiosity, have you tried the tuned irq plugin ? |
|
Also, I checked and only putting the interface manually down then up resets the affinity What SEAPATH concrete behavior would lead for ifupdown to be used ? Seems like a manual intervention to me. Sorry to be a bit picky, but I try to get the big picture here so that we can correct that the right way |
|
And last idea that I have in mind, If we really have to merge a script like that in SEAPATH, I would advise for python instead of bash for readability and maintainability |
|
Good question, I hadn't set up the tuned IRQ handling for this specifically, so take the following with a grain of salt, it's my current understanding rather than something I've benchmarked head-to-head. From what I can tell, tuned doesn't have a dedicated "irq" plugin that dynamically re-pins a given NIC's queues when the interface comes up. IRQ affinity is handled by the There's also a bit of tension with #985, where we're deliberately making tuned as inert as possible at runtime on a live node (disabling the That said, I want to be clear I'm not against reusing tuned in principle, and to your earlier suggestion, keeping/fixing the existing IRQ role is a perfectly safe, working and low-effort option too. The standalone monitor mostly appealed to me because it decouples the per-NIC affinity from tuned's apply/rollback cycle, which lines up with the direction of #985. But if you'd prefer to explore the tuned plugin route, I'm open to it, happy to test it if you think it can re-apply on link-up. |
|
On the down/up point, you're right, and thanks for actually testing it. Carrier loss and a The remaining justification I'd stand behind is ordering rather than frequency: with the oneshot you have to guarantee it runs after every managed interface's first On bash vs python: this was a deliberate switch, not an oversight. The daemon is essentially a thin loop around Happy to add comments to the parsing bit if the |
Problems with the previous implementation: 1. Boot-ordering fragility: /proc/irq/X/smp_affinity_list is reset when the kernel calls request_irq(), which happens in ndo_open() every time the interface is brought up. To be effective the oneshot therefore had to run *after* every managed interface's first ndo_open() at boot — an ordering that is hard to guarantee across networkd/NetworkManager/ifupdown. If it ran too early, its writes were discarded when the interface came up. 2. Driver reload not covered: modprobe -r / modprobe causes the device to disappear and reappear. The oneshot service was never re-triggered in these cases. 3. Race with irqbalance: the service ran After=irqbalance.service but irqbalance is a daemon that continuously rebalances IRQs (every ~10s), overwriting the affinity within seconds. 4. Wrong script location: the Python script was deployed to /etc/systemd/system/, mixing executables into the systemd unit directory. 5. Unnecessary complexity: the Python script did nothing more than iterate /proc/irq/ and write to smp_affinity_list — a few lines of shell. Replace with a long-running daemon based on ip monitor link. This monitors RTM_NEWLINK messages via the kernel netlink socket, which is independent of the network manager in use (networkd, NetworkManager, ifupdown all produce the same netlink events). The UP event is delivered after ndo_open() completes, so IRQs are registered in /proc/irq/ with their default affinity when we apply the configured affinity — correct by construction, regardless of boot ordering. The daemon also applies affinity at startup for interfaces already up, covering manual service restarts. With Restart=always it survives crashes and re-applies on driver reload or an ethtool channel/ring change. Legacy service and files are cleaned up on existing hosts. Signed-off-by: Florent Carli <florent.carli@rte-france.com>
Problems with the previous implementation:
Boot-ordering fragility: /proc/irq/X/smp_affinity_list is reset when the kernel calls request_irq(), which happens in ndo_open() every time the interface is brought up. To be effective the oneshot therefore had to run after every managed interface's first ndo_open() at boot: an ordering that is hard to guarantee across networkd/NetworkManager/ifupdown. If it ran too early, its writes were discarded when the interface came up.
Driver reload not covered: modprobe -r / modprobe causes the device to disappear and reappear. The oneshot service was never re-triggered in these cases.
Race with irqbalance: the service ran After=irqbalance.service but irqbalance is a daemon that continuously rebalances IRQs (every ~10s), overwriting the affinity within seconds.
Wrong script location: the Python script was deployed to /etc/systemd/system/, mixing executables into the systemd unit directory.
Unnecessary complexity: the Python script did nothing more than iterate /proc/irq/ and write to smp_affinity_list, a few lines of shell.
Replace with a long-running daemon based on ip monitor link. This monitors RTM_NEWLINK messages via the kernel netlink socket, which is independent of the network manager in use (networkd, NetworkManager, ifupdown all produce the same netlink events). The UP event is delivered after ndo_open() completes, so IRQs are registered in /proc/irq/ with their default affinity when we apply the configured affinity: correct by construction, regardless of boot ordering.
The daemon also applies affinity at startup for interfaces already up, covering manual service restarts. With Restart=always it survives crashes and re-applies on driver reload or an ethtool channel/ring change.
Note: carrier events (cable unplug/replug) and a network-manager restart do not re-open the device, so they do not reset the affinity and need no handling. The reset only occurs on an actual ndo_open() (first boot bring-up, admin down/up, driver reload, ethtool channel/ring change).
Legacy service and files are cleaned up on existing hosts.