Index: sys/net/if.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/if.c,v diff -u -p -u -p -r1.722 if.c --- sys/net/if.c 16 Jan 2025 17:20:23 -0000 1.722 +++ sys/net/if.c 18 Jan 2025 23:15:49 -0000 @@ -981,6 +981,7 @@ void if_input_process(struct ifnet *ifp, struct mbuf_list *ml) { struct mbuf *m; + struct softnet_storage thread_storage; if (ml_empty(ml)) return; @@ -995,10 +996,23 @@ if_input_process(struct ifnet *ifp, stru * read only or MP safe. Usually they hold the exclusive net lock. */ + ml_init(&thread_storage.sns_ml_tcp); + ml_init(&thread_storage.sns_ml_tcp6); + NET_LOCK_SHARED(); - while ((m = ml_dequeue(ml)) != NULL) + while ((m = ml_dequeue(ml)) != NULL) { + m->m_pkthdr.ph_cookie = &thread_storage; (*ifp->if_input)(ifp, m); + } NET_UNLOCK_SHARED(); + + if (!ml_empty(&thread_storage.sns_ml_tcp) || + !ml_empty(&thread_storage.sns_ml_tcp6)) { + NET_LOCK(); + tcp_input_mlist(&thread_storage.sns_ml_tcp, AF_INET); + tcp_input_mlist(&thread_storage.sns_ml_tcp6, AF_INET6); + NET_UNLOCK(); + } } void Index: sys/net/if_var.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/net/if_var.h,v diff -u -p -u -p -r1.133 if_var.h --- sys/net/if_var.h 12 Oct 2024 23:18:10 -0000 1.133 +++ sys/net/if_var.h 18 Jan 2025 23:15:49 -0000 @@ -292,6 +292,11 @@ struct ifg_list { #define IF_WWAN_DEFAULT_PRIORITY 6 #define IF_CARP_DEFAULT_PRIORITY 15 +struct softnet_storage { + struct mbuf_list sns_ml_tcp; + struct mbuf_list sns_ml_tcp6; +}; + /* * Network stack input queues. */ Index: sys/netinet/in_proto.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/in_proto.c,v diff -u -p -u -p -r1.121 in_proto.c --- sys/netinet/in_proto.c 5 Jan 2025 12:36:48 -0000 1.121 +++ sys/netinet/in_proto.c 18 Jan 2025 23:15:49 -0000 @@ -197,7 +197,8 @@ const struct protosw inetsw[] = { .pr_type = SOCK_STREAM, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_TCP, - .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE| + PR_MPINPUT, .pr_input = tcp_input, .pr_ctlinput = tcp_ctlinput, .pr_ctloutput = tcp_ctloutput, Index: sys/netinet/tcp_input.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/tcp_input.c,v diff -u -p -u -p -r1.423 tcp_input.c --- sys/netinet/tcp_input.c 16 Jan 2025 11:59:20 -0000 1.423 +++ sys/netinet/tcp_input.c 18 Jan 2025 23:15:49 -0000 @@ -100,9 +100,6 @@ #include #endif -int tcp_mss_adv(struct mbuf *, int); -int tcp_flush_queue(struct tcpcb *); - #ifdef INET6 #include #include @@ -177,6 +174,9 @@ do { \ if_put(ifp); \ } while (0) +int tcp_input_mbuf(struct mbuf **, int *, int, int); +int tcp_mss_adv(struct mbuf *, int); +int tcp_flush_queue(struct tcpcb *); void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); void tcp_newreno_partialack(struct tcpcb *, struct tcphdr *); @@ -347,12 +347,54 @@ tcp_flush_queue(struct tcpcb *tp) return (flags); } +int +tcp_input(struct mbuf **mp, int *offp, int proto, int af) +{ + struct softnet_storage *thread_storage; + struct mbuf_list *ml; + + thread_storage = (*mp)->m_pkthdr.ph_cookie; + if (thread_storage == NULL) + return tcp_input_mbuf(mp, offp, proto, af); + + (*mp)->m_pkthdr.ph_cookie = (void *)(long)(*offp); + switch (af) { + case AF_INET: + ml = &thread_storage->sns_ml_tcp; + break; +#ifdef INET6 + case AF_INET6: + ml = &thread_storage->sns_ml_tcp6; + break; +#endif + default: + unhandled_af(af); + } + ml_enqueue(ml, *mp); + *mp = NULL; + return IPPROTO_DONE; +} + +void +tcp_input_mlist(struct mbuf_list *ml, int af) +{ + struct mbuf *m; + int off, nxt; + + while ((m = ml_dequeue(ml)) != NULL) { + off = (long)m->m_pkthdr.ph_cookie; + m->m_pkthdr.ph_cookie = NULL; + nxt = tcp_input_mbuf(&m, &off, IPPROTO_TCP, af); + KASSERT(nxt == IPPROTO_DONE); + } +} + /* * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ int -tcp_input(struct mbuf **mp, int *offp, int proto, int af) +tcp_input_mbuf(struct mbuf **mp, int *offp, int proto, int af) { struct mbuf *m = *mp; int iphlen = *offp; Index: sys/netinet/tcp_var.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/tcp_var.h,v diff -u -p -u -p -r1.185 tcp_var.h --- sys/netinet/tcp_var.h 16 Jan 2025 11:59:20 -0000 1.185 +++ sys/netinet/tcp_var.h 18 Jan 2025 23:15:49 -0000 @@ -718,6 +718,7 @@ int tcp_dooptions(struct tcpcb *, u_cha struct mbuf *, int, struct tcp_opt_info *, u_int, uint64_t); void tcp_init(void); int tcp_input(struct mbuf **, int *, int, int); +void tcp_input_mlist(struct mbuf_list *, int); int tcp_mss(struct tcpcb *, int); void tcp_mss_update(struct tcpcb *); u_int tcp_hdrsz(struct tcpcb *); Index: sys/netinet6/in6_proto.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet6/in6_proto.c,v diff -u -p -u -p -r1.124 in6_proto.c --- sys/netinet6/in6_proto.c 5 Jan 2025 12:36:48 -0000 1.124 +++ sys/netinet6/in6_proto.c 18 Jan 2025 23:15:49 -0000 @@ -147,7 +147,8 @@ const struct protosw inet6sw[] = { .pr_type = SOCK_STREAM, .pr_domain = &inet6domain, .pr_protocol = IPPROTO_TCP, - .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE| + PR_MPINPUT, .pr_input = tcp_input, .pr_ctlinput = tcp6_ctlinput, .pr_ctloutput = tcp_ctloutput,