From: Chris Cappuccio Subject: Re: vio: Enable multiqueue To: Stefan Fritsch Cc: Hrvoje Popovski , tech@openbsd.org Date: Sun, 26 Jan 2025 12:59:13 -0800 Stefan Fritsch [sf@openbsd.org] wrote: > > diff --git a/sys/net/ifq.c b/sys/net/ifq.c > index 7368aa50a57..547cfb26d84 100644 > --- a/sys/net/ifq.c > +++ b/sys/net/ifq.c > @@ -903,6 +903,8 @@ priq_idx(unsigned int nqueues, const struct mbuf *m) > > if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) > flow = m->m_pkthdr.ph_flowid; > + else > + flow = cpu_number(); > > return (flow % nqueues); > } If you generalize the idea of pf_pkt_hash, and stick it in the wrong place, it might look like this. Index: ifq.c =================================================================== RCS file: /cvs/src/sys/net/ifq.c,v retrieving revision 1.55 diff -u -p -u -r1.55 ifq.c --- ifq.c 20 Nov 2024 02:18:45 -0000 1.55 +++ ifq.c 26 Jan 2025 20:54:51 -0000 @@ -29,6 +29,11 @@ #include #include +#include +#include +#include +#include + #if NBPFILTER > 0 #include #endif @@ -892,6 +897,60 @@ net_ifiq_sysctl(int *name, u_int namelen return (error); } +unsigned int +ifq_pkt_hash(const struct mbuf *m) +{ + unsigned int hash = 0; + uint8_t ip_version; + const uint16_t *ports = NULL; + const struct ip *ip_hdr; + const struct ip6_hdr *ip6_hdr; + uint8_t proto = 0; + + ip_version = (*mtod(m, uint8_t *) >> 4); + switch (ip_version) { + case 4: + ip_hdr = mtod(m, const struct ip *); + if (m->m_len < (ip_hdr->ip_hl << 2)) { + return 0; + } + hash ^= ip_hdr->ip_src.s_addr; + hash ^= ip_hdr->ip_dst.s_addr; + proto = ip_hdr->ip_p; + if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) { + ports = (const uint16_t *)((uint8_t *)ip_hdr + + (ip_hdr->ip_hl << 2)); + hash ^= *(const uint32_t *)ports; + } + break; + case 6: + ip6_hdr = mtod(m, const struct ip6_hdr *); + if (m->m_len < sizeof(struct ip6_hdr)) { + return 0; + } + hash ^= ip6_hdr->ip6_src.__u6_addr.__u6_addr32[0]; + hash ^= ip6_hdr->ip6_src.__u6_addr.__u6_addr32[1]; + hash ^= ip6_hdr->ip6_src.__u6_addr.__u6_addr32[2]; + hash ^= ip6_hdr->ip6_src.__u6_addr.__u6_addr32[3]; + hash ^= ip6_hdr->ip6_dst.__u6_addr.__u6_addr32[0]; + hash ^= ip6_hdr->ip6_dst.__u6_addr.__u6_addr32[1]; + hash ^= ip6_hdr->ip6_dst.__u6_addr.__u6_addr32[2]; + hash ^= ip6_hdr->ip6_dst.__u6_addr.__u6_addr32[3]; + proto = ip6_hdr->ip6_nxt; + if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) { + ports = (const uint16_t *)((uint8_t *)ip6_hdr + + sizeof(struct ip6_hdr)); + hash ^= *(const uint32_t *)ports; + } + break; + default: + return stoeplitz_n32(*(const uint32_t *) + mtod(m, const uint8_t *)); + } + + return stoeplitz_n32(hash); +} + /* * priq implementation */ @@ -903,6 +962,8 @@ priq_idx(unsigned int nqueues, const str if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) flow = m->m_pkthdr.ph_flowid; + else + flow = ifq_pkt_hash(m); return (flow % nqueues); }