tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: pluggable pktq_rps_hash()
> Date: Thu, 7 Oct 2021 12:06:08 +0900
> From: Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>
>
> On 2021/09/24 13:27, Kengo NAKAHARA wrote:
> > Hi,
> >
> > I implement some of pktq_rps_hash() and make pluggable it for each
> > interface type such as ether, pppoe, gif, and ipsecif.
> > Here is the patch
> > https://github.com/knakahara/netbsd-src/commit/68a43105b541aec79c6f067e81dbe34ad2282dec
> >
> > Of course, the default behavior is not changed. We can change RPS
> > behavior by "sysctl -w net.{ether,pppoe,gif,ipsecif}.rps_hash=${value}".
> > Currently, the values are
> > - zero : always return 0
> > - curcpu : return current cpuid
> > - toeplitz : return toeplitz hash value which calculated from mbuf
> >
> > I think it is easy to add new rps hash functions to the above patch
> > and to apply the pluggable rps hash function to other interfaces.
> >
> > Could you comment the patch?
Looks reasonable! Some minor comments:
- Where you do atomic_swap_ptr(func, ...) and discard the result, you
should just do atomic_store_relaxed(func, ...) instead. Cheaper way
to get the same effect.
- pktqueue.c, pktq_rps_hash_toeplitz, line 266:
}
else if (...) {
should be
} else if (...) {
- In the sysctl definitions, no need for explicit (void *) cast.
- Indentation in the sysctl_createv calls is a little confusing -- I
suggest putting `CTL_CREATE, CTL_EOL' on its own line to make it
clear that `PKTQ_RPS_HASH_NAME_LEN' is not actually part of the
sysctl mib.
(Is it necessary to pass PKTQ_RPS_HASH_NAME_LEN, anyway? A lot of
sysctl_createv calls just pass zero here. I can't tell from the man
page what it does.)
- pktqueue.c, sysctl_pktq_rps_hash_handler, lines 320 and 325: no need
for a stack buffer to copy the type name into; can just do
const char *type;
...
type = pktq_get_rps_hash_type(*func);
- Instead of copying & pasting the conditional default everywhere,
static pktq_rps_hash_func_t xyzif_pktq_rps_hash_p =
#ifdef NET_MPSAFE
pktq_rps_hash_curcpu;
#else
pktq_rps_hash_zero;
#endif
how about defining a default in pktqueue.c/h and using that
everywhere?
static pktq_rps_hash_func_t xyzif_pktq_rps_hash_p =
pktq_rps_hash_default;
Or is there a reason to make the default subsystem-specific?
- Could avoid writing lots of subsystem-specific wrapper functions
like ether_pktq_rps_hash by defining a function to call the
subsystem-specific pktq rps hash function:
/* pktqueue.c */
uint32_t
pktq_rps_hash(pktq_rps_hash_func_t *funcp, struct mbuf *m)
{
pktq_rps_hash_func_t func = atomic_load_relaxed(funcp);
KASSERT(func != NULL);
return (*func)(m);
}
/* if_ethersubr.c */
const uint32_t h = pktq_rps_hash(ðer_pktq_rps_hash_p, m);
This would also avoid triggering sanitizers which object to loading
ether_pktq_rps_hash_p with a non-atomic load. (Not actually a
problem on any CPUs we care about, but helps reduce false alarms
from sanitizers.)
This would also give us more flexibility if the pktq rps hash had
more state, e.g. maybe a random seed alongside it. (Not sure that's
an important avenue of flexibility, but it keeps the API details
more neatly confined to pktqueue.c.)
Home |
Main Index |
Thread Index |
Old Index