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 20 Jan 2025 09:54:45 -0000 @@ -244,11 +244,6 @@ int ifq_congestion; int netisr; -struct softnet { - char sn_name[16]; - struct taskq *sn_taskq; -}; - #define NET_TASKQ 4 struct softnet softnets[NET_TASKQ]; @@ -978,9 +973,10 @@ 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, u_int idx) { struct mbuf *m; + struct softnet *sn; if (ml_empty(ml)) return; @@ -995,10 +991,22 @@ if_input_process(struct ifnet *ifp, stru * read only or MP safe. Usually they hold the exclusive net lock. */ + sn = &softnets[idx]; + ml_init(&sn->sn_tcp_ml); + NET_LOCK_SHARED(); - while ((m = ml_dequeue(ml)) != NULL) + while ((m = ml_dequeue(ml)) != NULL) { + /* add 1 to index, 0 means not set */ + m->m_pkthdr.ph_softidx = idx + 1; (*ifp->if_input)(ifp, m); + } NET_UNLOCK_SHARED(); + + if (!ml_empty(&sn->sn_tcp_ml)) { + NET_LOCK(); + tcp_input_mlist(&sn->sn_tcp_ml); + 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 20 Jan 2025 09:54:45 -0000 @@ -292,6 +292,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 mbuf_list sn_tcp_ml; +}; + +extern struct softnet softnets[]; + /* * Network stack input queues. */ @@ -322,7 +330,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 *, u_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.55 ifq.c --- sys/net/ifq.c 20 Nov 2024 02:18:45 -0000 1.55 +++ sys/net/ifq.c 20 Jan 2025 09:54:45 -0000 @@ -849,7 +849,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/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 20 Jan 2025 09:54:45 -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 20 Jan 2025 09:54:45 -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,44 @@ tcp_flush_queue(struct tcpcb *tp) return (flags); } +int +tcp_input(struct mbuf **mp, int *offp, int proto, int af) +{ + struct softnet *sn; + + if ((*mp)->m_pkthdr.ph_softidx == 0) + return tcp_input_mbuf(mp, offp, proto, af); + sn = &softnets[(*mp)->m_pkthdr.ph_softidx - 1]; + (*mp)->m_pkthdr.ph_softidx = 0; + (*mp)->m_pkthdr.ph_cookie = (void *)(long)(*offp); + (*mp)->m_pkthdr.ph_family = af; + ml_enqueue(&sn->sn_tcp_ml, *mp); + *mp = NULL; + return IPPROTO_DONE; +} + +void +tcp_input_mlist(struct mbuf_list *ml) +{ + struct mbuf *m; + + while ((m = ml_dequeue(ml)) != NULL) { + int off, nxt, af; + + off = (long)m->m_pkthdr.ph_cookie; + m->m_pkthdr.ph_cookie = NULL; + af = m->m_pkthdr.ph_family; + 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 20 Jan 2025 09:54:45 -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 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 20 Jan 2025 09:54:45 -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, 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 20 Jan 2025 09:54:45 -0000 @@ -128,7 +128,7 @@ struct pkthdr { 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; };