Download raw body.
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 <net/if.h>
#include <net/if_var.h>
+#include <net/toeplitz.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+
#if NBPFILTER > 0
#include <net/bpf.h>
#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);
}