Index: sys/net/if.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/if.c,v diff -u -p -u -p -r1.726 if.c --- sys/net/if.c 3 Feb 2025 08:58:52 -0000 1.726 +++ sys/net/if.c 18 Feb 2025 00:25:08 -0000 @@ -241,19 +241,10 @@ struct rwlock if_tmplist_lock = RWLOCK_I struct mutex if_hooks_mtx = MUTEX_INITIALIZER(IPL_NONE); void if_hooks_run(struct task_list *); -int ifq_congestion; - -int netisr; - -struct softnet { - char sn_name[16]; - struct taskq *sn_taskq; -}; - -#define NET_TASKQ 4 +int ifq_congestion; +int netisr; struct softnet softnets[NET_TASKQ]; - -struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); +struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); /* * Serialize socket operations to ensure no new sleeping points @@ -979,7 +970,7 @@ if_output_local(struct ifnet *ifp, struc } void -if_input_process(struct ifnet *ifp, struct mbuf_list *ml) +if_input_process(struct ifnet *ifp, struct mbuf_list *ml, unsigned int idx) { struct mbuf *m; @@ -996,9 +987,14 @@ if_input_process(struct ifnet *ifp, stru * read only or MP safe. Usually they hold the exclusive net lock. */ + idx = net_idx(idx); + KASSERT(idx < 256 - 1); + NET_LOCK_SHARED(); - while ((m = ml_dequeue(ml)) != NULL) + while ((m = ml_dequeue(ml)) != NULL) { + m->m_pkthdr.ph_softidx = idx + 1; (*ifp->if_input)(ifp, m); + } NET_UNLOCK_SHARED(); } @@ -3672,16 +3668,23 @@ unhandled_af(int af) panic("unhandled af %d", af); } -struct taskq * -net_tq(unsigned int ifindex) +unsigned int +net_idx(unsigned int ifindex) { - struct softnet *sn; static int nettaskqs; if (nettaskqs == 0) nettaskqs = min(NET_TASKQ, ncpus); - sn = &softnets[ifindex % nettaskqs]; + return (ifindex % nettaskqs); +} + +struct taskq * +net_tq(unsigned int ifindex) +{ + struct softnet *sn; + + sn = &softnets[net_idx(ifindex)]; return (sn->sn_taskq); } Index: sys/net/if.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/if.h,v diff -u -p -u -p -r1.217 if.h --- sys/net/if.h 9 Jun 2024 16:25:28 -0000 1.217 +++ sys/net/if.h 18 Feb 2025 00:25:08 -0000 @@ -560,7 +560,10 @@ void if_congestion(void); int if_congested(void); __dead void unhandled_af(int); int if_setlladdr(struct ifnet *, const uint8_t *); -struct taskq * net_tq(unsigned int); +unsigned int + net_idx(unsigned int); +struct taskq * + net_tq(unsigned int); void net_tq_barriers(const char *); #endif /* _KERNEL */ Index: sys/net/if_var.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/if_var.h,v diff -u -p -u -p -r1.135 if_var.h --- sys/net/if_var.h 24 Jan 2025 09:19:07 -0000 1.135 +++ sys/net/if_var.h 18 Feb 2025 00:25:08 -0000 @@ -46,6 +46,7 @@ #include #include +#include /* * Structures defining a network interface, providing a packet @@ -301,6 +302,14 @@ struct ifg_list { #define IF_WWAN_DEFAULT_PRIORITY 6 #define IF_CARP_DEFAULT_PRIORITY 15 +struct softnet { + char sn_name[16]; + struct taskq *sn_taskq; + struct route sn_route; +} __aligned(64); +#define NET_TASKQ 4 +extern struct softnet softnets[NET_TASKQ]; + /* * Network stack input queues. */ @@ -331,7 +340,7 @@ int if_enqueue(struct ifnet *, struct mb int if_enqueue_ifq(struct ifnet *, struct mbuf *); void if_input(struct ifnet *, struct mbuf_list *); void if_vinput(struct ifnet *, struct mbuf *); -void if_input_process(struct ifnet *, struct mbuf_list *); +void if_input_process(struct ifnet *, struct mbuf_list *, unsigned int); int if_input_local(struct ifnet *, struct mbuf *, sa_family_t); int if_output_ml(struct ifnet *, struct mbuf_list *, struct sockaddr *, struct rtentry *); Index: sys/net/ifq.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/ifq.c,v diff -u -p -u -p -r1.56 ifq.c --- sys/net/ifq.c 3 Feb 2025 08:58:52 -0000 1.56 +++ sys/net/ifq.c 18 Feb 2025 00:25:08 -0000 @@ -862,7 +862,7 @@ ifiq_process(void *arg) ml_init(&ifiq->ifiq_ml); mtx_leave(&ifiq->ifiq_mtx); - if_input_process(ifiq->ifiq_if, &ml); + if_input_process(ifiq->ifiq_if, &ml, ifiq->ifiq_idx); } int Index: sys/netinet/ip_input.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/ip_input.c,v diff -u -p -u -p -r1.403 ip_input.c --- sys/netinet/ip_input.c 3 Jan 2025 21:27:40 -0000 1.403 +++ sys/netinet/ip_input.c 18 Feb 2025 00:25:08 -0000 @@ -441,7 +441,7 @@ bad: int ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { - struct route ro; + struct route iproute, *ro = NULL; struct mbuf *m; struct ip *ip; int hlen; @@ -452,7 +452,6 @@ ip_input_if(struct mbuf **mp, int *offp, KASSERT(*offp == 0); - ro.ro_rt = NULL; ipstat_inc(ips_total); m = *mp = ipv4_check(ifp, *mp); if (m == NULL) @@ -512,7 +511,16 @@ ip_input_if(struct mbuf **mp, int *offp, goto out; } - switch(in_ouraddr(m, ifp, &ro, flags)) { + if ((*mp)->m_pkthdr.ph_softidx == 0) { + ro = &iproute; + ro->ro_rt = NULL; + } else { + struct softnet *sn; + + sn = &softnets[m->m_pkthdr.ph_softidx - 1]; + ro = &sn->sn_route; + } + switch(in_ouraddr(m, ifp, ro, flags)) { case 2: goto bad; case 1: @@ -614,15 +622,17 @@ ip_input_if(struct mbuf **mp, int *offp, } #endif /* IPSEC */ - ip_forward(m, ifp, &ro, flags); + ip_forward(m, ifp, ro, flags); *mp = NULL; - rtfree(ro.ro_rt); + if (ro == &iproute) + rtfree(ro->ro_rt); return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: - rtfree(ro.ro_rt); + if (ro == &iproute) + rtfree(ro->ro_rt); return nxt; } Index: sys/netinet6/ip6_input.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet6/ip6_input.c,v diff -u -p -u -p -r1.267 ip6_input.c --- sys/netinet6/ip6_input.c 21 Nov 2024 20:15:44 -0000 1.267 +++ sys/netinet6/ip6_input.c 18 Feb 2025 00:25:08 -0000 @@ -362,7 +362,7 @@ bad: int ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) { - struct route ro; + struct route iproute, *ro = NULL; struct mbuf *m; struct ip6_hdr *ip6; struct rtentry *rt; @@ -375,7 +375,6 @@ ip6_input_if(struct mbuf **mp, int *offp KASSERT(*offp == 0); - ro.ro_rt = NULL; ip6stat_inc(ip6s_total); m = *mp = ipv6_check(ifp, *mp); if (m == NULL) @@ -533,7 +532,18 @@ ip6_input_if(struct mbuf **mp, int *offp /* * Unicast check */ - rt = route6_mpath(&ro, &ip6->ip6_dst, &ip6->ip6_src, + if ((*mp)->m_pkthdr.ph_cookie == NULL) { + ro = &iproute; + ro->ro_rt = NULL; + } else { + struct softnet *sn; + + sn = (*mp)->m_pkthdr.ph_cookie; + /* sanity check that noone else uses mbuf cookie */ + KASSERT(sn >= softnets && sn < softnets + sizeof(softnets)); + ro = &sn->sn_route; + } + rt = route6_mpath(ro, &ip6->ip6_dst, &ip6->ip6_src, m->m_pkthdr.ph_rtableid); /* @@ -631,15 +641,17 @@ ip6_input_if(struct mbuf **mp, int *offp } #endif /* IPSEC */ - ip6_forward(m, &ro, flags); + ip6_forward(m, ro, flags); *mp = NULL; - rtfree(ro.ro_rt); + if (ro == &iproute) + rtfree(ro->ro_rt); return IPPROTO_DONE; bad: nxt = IPPROTO_DONE; m_freemp(mp); out: - rtfree(ro.ro_rt); + if (ro == &iproute) + rtfree(ro->ro_rt); return nxt; } Index: sys/sys/mbuf.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/sys/mbuf.h,v diff -u -p -u -p -r1.265 mbuf.h --- sys/sys/mbuf.h 5 Nov 2024 13:15:13 -0000 1.265 +++ sys/sys/mbuf.h 18 Feb 2025 00:25:08 -0000 @@ -122,13 +122,13 @@ struct pkthdr_pf { #endif /* record/packet header in first mbuf of chain; valid if M_PKTHDR set */ -struct pkthdr { +struct pkthdr { void *ph_cookie; /* additional data */ SLIST_HEAD(, m_tag) ph_tags; /* list of packet tags */ int64_t ph_timestamp; /* packet timestamp */ int len; /* total packet length */ u_int ph_rtableid; /* routing table id */ - u_int ph_ifidx; /* rcv interface index */ + u_int16_t ph_ifidx; /* rcv interface index */ u_int16_t ph_tagsset; /* mtags attached */ u_int16_t ph_flowid; /* pseudo unique flow id */ u_int16_t csum_flags; /* checksum flags */ @@ -136,6 +136,8 @@ struct pkthdr { u_int16_t ph_mss; /* TCP max segment size */ u_int8_t ph_loopcnt; /* mbuf is looping in kernel */ u_int8_t ph_family; /* af, used when queueing */ + u_int8_t ph_softidx; /* index of softnet thread */ + u_int8_t ph_pad[1]; struct pkthdr_pf pf; };