More and more code migrates from lock-based protection to the NET_EPOCH umbrella.
It requires some logic changes, including, notably, refcount handling.
When we have an ifp pointer and we're running inside epoch we're guaranteed that this pointer will not be freed.
However, the following case can still happen:
- in thread 1 we drop to 0 refcount for ifp and schedule its deletion.
- in thread 2 we use this ifp and reference it
- destroy callout kicks in
- unhappy user reports bug
This can happen with the current implementation of ifnet_byindex_ref(), as we're not holding any locks preventing ifnet deletion by a parallel thread.
To address it, if_try_ref() function is added, allowing to return failure when we try to reference ifp with 0 refcount.
Additionally, existing if_ref() is enforced with KASSERT to provide a cleaner error in such scenarios.
Finally, fix ifnet_byindex_ref() by using if_try_ref() and returning NULL if the latter fails.
This is pretty much the same as D28639.
If mips32 + SMP ends up not being a thing anymore due to the recent 64-bit atomic debate, this function can just be removed.
Otherwise, is there a good way for me to exercise that config? I'm open to buying real HW...