From e6f77b88e961aed05f67575815c0480d45443878 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 22 Jul 2011 18:29:11 +0800 Subject: [PATCH] netisr: Add hashcheck method to check and adjust hw provided hash Currently only IPv4 provides the non-default hashcheck method For IPv4's hashcheck: - Fragements are always delivered to CPU0 - non-TCP and non-UDP packets are passed to software for hash calculation --- sys/net/if_ethersubr.c | 12 +++++++----- sys/net/netisr.c | 38 ++++++++++++++++++++++++++++++++++++++ sys/net/netisr.h | 5 ++++- sys/net/netmsg.h | 3 +++ sys/netinet/ip_demux.c | 27 +++++++++------------------ sys/netinet/ip_input.c | 1 + sys/netinet/ip_var.h | 1 + 7 files changed, 63 insertions(+), 24 deletions(-) diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 5dcc9d7103..4b01050375 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1586,13 +1586,15 @@ ether_input_chain(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi, #ifdef RSS_DEBUG ether_pktinfo_try++; #endif - ether_dispatch(pi->pi_netisr, m, chain); - + netisr_hashcheck(pi->pi_netisr, m, pi); + if (m->m_flags & M_HASH) { + ether_dispatch(pi->pi_netisr, m, chain); #ifdef RSS_DEBUG - ether_pktinfo_hit++; + ether_pktinfo_hit++; #endif - logether(chain_end, ifp); - return; + logether(chain_end, ifp); + return; + } } #ifdef RSS_DEBUG else if (ifp->if_capenable & IFCAP_RSS) { diff --git a/sys/net/netisr.c b/sys/net/netisr.c index 8dbbcf1849..5253bf45af 100644 --- a/sys/net/netisr.c +++ b/sys/net/netisr.c @@ -60,6 +60,7 @@ static void netmsg_sync_func(netmsg_t msg); static void netmsg_service_loop(void *arg); static void cpu0_cpufn(struct mbuf **mp, int hoff); +static void netisr_nohashck(struct mbuf *, const struct pktinfo *); struct netmsg_port_registration { TAILQ_ENTRY(netmsg_port_registration) npr_entry; @@ -443,10 +444,23 @@ netisr_register(int num, netisr_fn_t handler, netisr_cpufn_t cpufn) ni = &netisrs[num]; ni->ni_handler = handler; + ni->ni_hashck = netisr_nohashck; ni->ni_cpufn = cpufn; netmsg_init(&ni->ni_netmsg, NULL, &netisr_adone_rport, 0, NULL); } +void +netisr_register_hashcheck(int num, netisr_hashck_t hashck) +{ + struct netisr *ni; + + KASSERT((num > 0 && num <= NELEM(netisrs)), + ("netisr_register: bad isr %d", num)); + + ni = &netisrs[num]; + ni->ni_hashck = hashck; +} + void netisr_register_rollup(netisr_ru_t ru_func) { @@ -663,3 +677,27 @@ netisr_barrier_rem(struct netisr_barrier *br) #endif br->br_isset = 0; } + +static void +netisr_nohashck(struct mbuf *m, const struct pktinfo *pi __unused) +{ + m->m_flags &= ~M_HASH; +} + +void +netisr_hashcheck(int num, struct mbuf *m, const struct pktinfo *pi) +{ + struct netisr *ni; + + if (num < 0 || num >= NETISR_MAX) + panic("Bad isr %d", num); + + /* + * Valid netisr? + */ + ni = &netisrs[num]; + if (ni->ni_handler == NULL) + panic("Unregistered isr %d\n", num); + + ni->ni_hashck(m, pi); +} diff --git a/sys/net/netisr.h b/sys/net/netisr.h index b60ce5c191..8126176685 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -151,7 +151,7 @@ struct pktinfo { */ struct netisr { netisr_fn_t ni_handler; /* packet handler function */ - netisr_ru_t ni_rufunc; /* rollup function */ + netisr_hashck_t ni_hashck; /* hash check function */ netisr_cpufn_t ni_cpufn; /* characterize pkt return cpu */ struct netmsg_base ni_netmsg; /* for sched_netisr() (no-data) */ }; @@ -173,9 +173,12 @@ lwkt_port_t cpu_portfn(int cpu); lwkt_port_t cur_netport(void); void netisr_register(int, netisr_fn_t, netisr_cpufn_t); +void netisr_register_hashcheck(int, netisr_hashck_t); void netisr_register_rollup(netisr_ru_t ru_func); 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 *); struct netisr_barrier *netisr_barrier_create(void); diff --git a/sys/net/netmsg.h b/sys/net/netmsg.h index 5e68985656..6e98259ea0 100644 --- a/sys/net/netmsg.h +++ b/sys/net/netmsg.h @@ -40,9 +40,12 @@ #include #endif +struct pktinfo; + typedef void (*netisr_fn_t)(netmsg_t); typedef void (*netisr_ru_t)(void); typedef void (*netisr_cpufn_t)(struct mbuf **, int); +typedef void (*netisr_hashck_t)(struct mbuf *, const struct pktinfo *); #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) diff --git a/sys/netinet/ip_demux.c b/sys/netinet/ip_demux.c index ac7894cd55..092adcbe7f 100644 --- a/sys/netinet/ip_demux.c +++ b/sys/netinet/ip_demux.c @@ -325,22 +325,19 @@ ip_cpufn_in(struct mbuf **mptr, int hoff) ip_cpufn(mptr, hoff, IP_MPORT_IN); } -#if 0 - /* - * Map a packet to a protocol processing thread and return the thread's port. + * Verify and adjust the hash value of the packet. + * * Unlike ip_cpufn(), the packet content is not accessed. The packet info - * (pi) and the hash of the packet (m_pkthdr.hash) is used instead. NULL is - * returned if the packet info does not contain enough information. + * (pi) and the hash of the packet (m_pkthdr.hash) is used instead. * * Caller has already made sure that m_pkthdr.hash is valid, i.e. m_flags * has M_HASH set. */ -lwkt_port_t -ip_mport_pktinfo(const struct pktinfo *pi, struct mbuf *m) +void +ip_hashcheck(struct mbuf *m, const struct pktinfo *pi) { - lwkt_port_t port; - + KASSERT((m->m_flags & M_HASH), ("no valid packet hash\n")); KASSERT(m->m_pkthdr.hash < ncpus2, ("invalid packet hash %#x\n", m->m_pkthdr.hash)); @@ -349,27 +346,21 @@ ip_mport_pktinfo(const struct pktinfo *pi, struct mbuf *m) */ if (pi->pi_flags & PKTINFO_FLAG_FRAG) { m->m_pkthdr.hash = 0; - return cpu_portfn(0); + return; } switch (pi->pi_l3proto) { case IPPROTO_TCP: - port = cpu_portfn(m->m_pkthdr.hash); - break; - case IPPROTO_UDP: - port = cpu_portfn(m->m_pkthdr.hash); break; default: - port = NULL; + /* Let software calculate the hash */ + m->m_flags &= ~M_HASH; break; } - return port; } -#endif - /* * This is used to map a socket to a message port for sendmsg() and friends. * It is not called for any other purpose. In the case of TCP we just return diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 0d277e7ecd..095d180943 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -379,6 +379,7 @@ ip_init(void) #endif netisr_register(NETISR_IP, ip_input_handler, ip_cpufn_in); + netisr_register_hashcheck(NETISR_IP, ip_hashcheck); } /* Do transport protocol processing. */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index e68e4c827b..eb5afc666f 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -202,6 +202,7 @@ extern int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, void ip_cpufn(struct mbuf **, int, int); void ip_cpufn_in(struct mbuf **, int); +void ip_hashcheck(struct mbuf *, const struct pktinfo *); boolean_t ip_lengthcheck(struct mbuf **, int); -- 2.41.0