From 234d1daa31c48c70cdb1381726e88c90a010c1fd Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 22 Aug 2012 09:19:25 +0800 Subject: [PATCH] ether: Add instrument to detect wrong hardware supplied hash If wrong hardware supplied hash is detected, the packet will be redispatched to the correct netisr --- sys/net/if_ethersubr.c | 59 +++++++++++++++++++++++++++++++++--------- sys/sys/mbuf.h | 3 ++- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 6923356ab9..4dbe21c799 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -115,6 +115,7 @@ static int ether_output(struct ifnet *, struct mbuf *, struct sockaddr *, static void ether_restore_header(struct mbuf **, const struct ether_header *, const struct ether_header *); static int ether_characterize(struct mbuf **); +static void ether_dispatch(int, struct mbuf *); /* * if_bridge support @@ -150,6 +151,8 @@ static u_long ether_pktinfo_hit; static u_long ether_rss_nopi; static u_long ether_rss_nohash; static u_long ether_input_requeue; +static u_long ether_input_wronghwhash; +static int ether_input_ckhash; #endif SYSCTL_DECL(_net_link); @@ -178,6 +181,10 @@ SYSCTL_ULONG(_net_link_ether, OID_AUTO, pktinfo_hit, CTLFLAG_RW, "# 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"); +SYSCTL_ULONG(_net_link_ether, OID_AUTO, input_wronghwhash, CTLFLAG_RW, + ðer_input_wronghwhash, 0, "# of input packets with wrong hw hash"); +SYSCTL_INT(_net_link_ether, OID_AUTO, always_ckhash, CTLFLAG_RW, + ðer_input_ckhash, 0, "always check hash"); #endif #define ETHER_KTR_STR "ifp=%p" @@ -1347,6 +1354,41 @@ ether_input_handler(netmsg_t nmsg) m = nmp->nm_packet; M_ASSERTPKTHDR(m); + + if ((m->m_flags & M_ETHER_VLANCHECKED) == 0) { + if (!ether_vlancheck(&m)) { + KKASSERT(m == NULL); + return; + } + } + if ((m->m_flags & (M_HASH | M_CKHASH)) == (M_HASH | M_CKHASH) +#ifdef RSS_DEBUG + || ether_input_ckhash +#endif + ) { + int isr; + + /* + * Need to verify the hash supplied by the hardware + * which could be wrong. + */ + m->m_flags &= ~(M_HASH | M_CKHASH); + isr = ether_characterize(&m); + if (m == NULL) + return; + KKASSERT(m->m_flags & M_HASH); + + if (m->m_pkthdr.hash != mycpuid) { + /* + * Wrong hardware supplied hash; redispatch + */ + ether_dispatch(isr, m); +#ifdef RSS_DEBUG + atomic_add_long(ðer_input_wronghwhash, 1); +#endif + return; + } + } ifp = m->m_pkthdr.rcvif; eh = mtod(m, struct ether_header *); @@ -1359,13 +1401,6 @@ ether_input_handler(netmsg_t nmsg) ifp->if_imcasts++; } - if ((m->m_flags & M_ETHER_VLANCHECKED) == 0) { - if (!ether_vlancheck(&m)) { - KKASSERT(m == NULL); - return; - } - } - ether_input_oncpu(ifp, m); } @@ -1470,12 +1505,12 @@ ether_input_pkt(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi) #endif /* - * Packet hash will be recalculated by software, - * so clear the M_HASH flag set by the driver; - * the hash value calculated by the hardware may - * not be exactly what we want. + * Packet hash will be recalculated by software, so clear + * the M_HASH and M_CKHASH flag set by the driver; the hash + * value calculated by the hardware may not be exactly what + * we want. */ - m->m_flags &= ~M_HASH; + m->m_flags &= ~(M_HASH | M_CKHASH); if (!ether_vlancheck(&m)) { KKASSERT(m == NULL); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 3300be089e..20f1763772 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -258,6 +258,7 @@ struct mbuf { #define M_PROTO6 0x200000/* protocol-specific */ #define M_PROTO7 0x400000/* protocol-specific */ #define M_PROTO8 0x800000/* protocol-specific */ +#define M_CKHASH 0x1000000/* hash needs software verification */ /* * Flags copied when copying m_pkthdr. @@ -266,7 +267,7 @@ struct mbuf { M_PROTO4|M_PROTO5|M_PROTO6|M_PROTO7|M_PROTO8 | \ M_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG | \ M_VLANTAG|M_MPLSLABELED | \ - M_LENCHECKED|M_HASH) + M_LENCHECKED|M_HASH|M_CKHASH) /* * Flags indicating hw checksum support and sw checksum requirements. -- 2.41.0