Page MenuHomeFreeBSD

Delayed context for SIOCADDMULTI
ClosedPublic

Authored by glebius on Oct 25 2019, 5:13 PM.
Tags
None
Referenced Files
F106401900: D22154.id63679.diff
Mon, Dec 30, 3:18 AM
Unknown Object (File)
Sat, Dec 21, 2:25 AM
Unknown Object (File)
Fri, Dec 20, 5:32 PM
Unknown Object (File)
Mon, Dec 16, 2:20 PM
Unknown Object (File)
Nov 28 2024, 10:36 AM
Unknown Object (File)
Nov 23 2024, 1:04 PM
Unknown Object (File)
Oct 27 2024, 5:19 PM
Unknown Object (File)
Oct 27 2024, 3:38 PM

Details

Summary

There is a long standing problem that IPv6 may call into if_ioctl(SIOCADDMULTI)
within the network input path, and some drivers may sleep in their if_ioctl.
This was always a problem with e1000 family of drivers, but conversion to iflib
has hidden the problem moving e1000 input packet processing into separate
taskqueue. The assertion no longer triggered, but the problem remained. Now
sleep won't block an interrupt, but will block the taskqueue thread, thus will
block the driver.

Now that all input network packet processing moved into network epoch context
we got assertion triggered again - sleep is prohibited.

Since nobody checks for return of if_ioctl() and there is nobody to report
the result to, there is no reason to run it synchronously. Thus, create
a task for that and in non-syscall contexts if_addmulti() should run the
if_ioctl via task.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 27222
Build 25486: arc lint + arc unit

Event Timeline

Please add code to drain this new task.

Drain the task. I'm not sure this is required as we reference the ifp, but
better safe than sorry.

sys/net/if.c
3543–3548

THREAD_CAN_SLEEP should include a check for epochnest?

3576

You should release the "ifp" pending number of times?

sys/net/if.c
3546

Maybe drop the refcounting. Makes it more complicated when calls are coalesched, and depend on drain of the taskqueue instead.

sys/net/if.c
1136

Can you check if this waits for any pending tasks? Or just cancel them w/o callback? Then you need to clean up the refcounting. As suggested, maybe the best is just to skip that.

Remove refcounting and rely on taskqueue_drain().

glebius added inline comments.
sys/net/if.c
3543–3548

THREAD_CAN_SLEEP should include a check for epochnest?

I'm discussing that with Kostik.

This revision is now accepted and ready to land.Oct 25 2019, 9:59 PM

Shouldn't there be a similar fix for if_delmulti? This change only addresses if_addmulti. If the change is not required for if_delmulti, can you add the justification for why it is not required.

Shouldn't the THREAD_CAN_SLEEP also check for in_epoch() test? I have come across threads that have the td_no_sleeping set to 0 and are inside an epoch section.

I think a delmultitask would be appropriate to avoid races on the if_ioctl handler, adding and removing multicast addresses.

Regarding in_epoch() in non-sleepable context, this is not an issue. Entering and exiting epoch should not block or sleep.

If you look at:

void
_epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et EPOCH_FILE_LINE)
{
...
        THREAD_NO_SLEEPING();

You find that in_epoch() implies THREAD_CAN_SLEEP() == 0 .

--HPS

I think a delmultitask would be appropriate to avoid races on the if_ioctl handler, adding and removing multicast addresses.

Regarding in_epoch() in non-sleepable context, this is not an issue. Entering and exiting epoch should not block or sleep.

Is there a change that adds if_delmultitask similar to r354149 which added if_addmultitask? I don't see one.

If you look at:

void
_epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et EPOCH_FILE_LINE)
{
...
        THREAD_NO_SLEEPING();

You find that in_epoch() implies THREAD_CAN_SLEEP() == 0 .

--HPS

Thanks for the responses.