From ebe4c2aed5905a679fc6d17112e471f23bb804af Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sun, 24 Jul 2011 19:50:08 +0800 Subject: [PATCH] ethernet: Allow netisr handler to run directly If the packet has already reach the correct netisr, we could simply call the netisr handler instead of requeue the packet. --- sys/net/if_ethersubr.c | 25 ++++++++++++++++++++++++- sys/net/netisr.c | 40 ++++++++++++++++++++++++++++++++++++++++ sys/net/netisr.h | 1 + 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index e6300c7a33..aa47d8872e 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -154,6 +154,7 @@ static boolean_t ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, static int ether_ipfw; static u_long ether_restore_hdr; static u_long ether_prepend_hdr; +static u_long ether_input_wronghash; static int ether_debug; #ifdef RSS_DEBUG @@ -161,6 +162,7 @@ static u_long ether_pktinfo_try; static u_long ether_pktinfo_hit; static u_long ether_rss_nopi; static u_long ether_rss_nohash; +static u_long ether_input_requeue; #endif SYSCTL_DECL(_net_link); @@ -174,6 +176,8 @@ SYSCTL_ULONG(_net_link_ether, OID_AUTO, restore_hdr, CTLFLAG_RW, SYSCTL_ULONG(_net_link_ether, OID_AUTO, prepend_hdr, CTLFLAG_RW, ðer_prepend_hdr, 0, "# of ether header restoration which prepends mbuf"); +SYSCTL_ULONG(_net_link_ether, OID_AUTO, input_wronghash, CTLFLAG_RW, + ðer_input_wronghash, 0, "# of input packets with wrong hash"); #ifdef RSS_DEBUG SYSCTL_ULONG(_net_link_ether, OID_AUTO, rss_nopi, CTLFLAG_RW, ðer_rss_nopi, 0, "# of packets do not have pktinfo"); @@ -185,6 +189,8 @@ SYSCTL_ULONG(_net_link_ether, OID_AUTO, pktinfo_try, CTLFLAG_RW, SYSCTL_ULONG(_net_link_ether, OID_AUTO, pktinfo_hit, CTLFLAG_RW, ðer_pktinfo_hit, 0, "# of packets whose msgport are found using pktinfo"); +SYSCTL_ULONG(_net_link_ether, OID_AUTO, input_requeue, CTLFLAG_RW, + ðer_input_requeue, 0, "# of input packets gets requeued"); #endif #define ETHER_KTR_STR "ifp=%p" @@ -1249,8 +1255,9 @@ post_stats: default: /* * The accurate msgport is not determined before - * we reach here, so redo the dispatching + * we reach here, so recharacterize packet. */ + m->m_flags &= ~M_HASH; #ifdef IPX if (ef_inputp) { /* @@ -1304,6 +1311,22 @@ dropanyway: return; } + if (m->m_flags & M_HASH) { + if (&curthread->td_msgport == cpu_portfn(m->m_pkthdr.hash)) { + netisr_handle(isr, m); + return; + } else { + /* + * XXX Something is wrong, + * we probably should panic here! + */ + m->m_flags &= ~M_HASH; + ether_input_wronghash++; + } + } +#ifdef RSS_DEBUG + ether_input_requeue++; +#endif netisr_queue(isr, m); } diff --git a/sys/net/netisr.c b/sys/net/netisr.c index 5253bf45af..a62c555a74 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -379,6 +379,46 @@ netisr_queue(int num, struct mbuf *m) return (0); } +/* + * Run a netisr service function on the packet. + * + * The packet must have been correctly characterized! + */ +int +netisr_handle(int num, struct mbuf *m) +{ + struct netisr *ni; + struct netmsg_packet *pmsg; + lwkt_port_t port; + + /* + * Get the protocol port based on the packet hash + */ + KASSERT((m->m_flags & M_HASH), ("packet not characterized\n")); + port = cpu_portfn(m->m_pkthdr.hash); + KASSERT(&curthread->td_msgport == port, ("wrong msgport\n")); + + KASSERT((num > 0 && num <= NELEM(netisrs)), ("bad isr %d", num)); + ni = &netisrs[num]; + if (ni->ni_handler == NULL) { + kprintf("unregistered isr %d\n", num); + m_freem(m); + return EIO; + } + + /* + * Initialize the netmsg, and run the handler directly. + */ + pmsg = &m->m_hdr.mh_netmsg; + netmsg_init(&pmsg->base, NULL, &netisr_apanic_rport, + 0, ni->ni_handler); + pmsg->nm_packet = m; + pmsg->base.lmsg.u.ms_result = num; + ni->ni_handler((netmsg_t)&pmsg->base); + + return 0; +} + /* * Pre-characterization of a deeper portion of the packet for the * requested isr. diff --git a/sys/net/netisr.h b/sys/net/netisr.h index 8126176685..9a2957c3d3 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -180,6 +180,7 @@ void netisr_characterize(int num, struct mbuf **mp, int hoff); void netisr_hashcheck(int num, struct mbuf *m, const struct pktinfo *pi); int netisr_queue(int, struct mbuf *); +int netisr_handle(int, struct mbuf *); struct netisr_barrier *netisr_barrier_create(void); void netisr_barrier_set(struct netisr_barrier *); -- 2.41.0