netisr: Add hashcheck method to check and adjust hw provided hash
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 22 Jul 2011 10:29:11 +0000 (18:29 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 22 Jul 2011 10:29:11 +0000 (18:29 +0800)
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
sys/net/netisr.c
sys/net/netisr.h
sys/net/netmsg.h
sys/netinet/ip_demux.c
sys/netinet/ip_input.c
sys/netinet/ip_var.h

index 5dcc9d7..4b01050 100644 (file)
@@ -1586,13 +1586,15 @@ ether_input_chain(struct ifnet *ifp, struct mbuf *m, const struct pktinfo *pi,
 #ifdef RSS_DEBUG
                ether_pktinfo_try++;
 #endif
 #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
 #ifdef RSS_DEBUG
-               ether_pktinfo_hit++;
+                       ether_pktinfo_hit++;
 #endif
 #endif
-               logether(chain_end, ifp);
-               return;
+                       logether(chain_end, ifp);
+                       return;
+               }
        }
 #ifdef RSS_DEBUG
        else if (ifp->if_capenable & IFCAP_RSS) {
        }
 #ifdef RSS_DEBUG
        else if (ifp->if_capenable & IFCAP_RSS) {
index 8dbbcf1..5253bf4 100644 (file)
@@ -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 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;
 
 struct netmsg_port_registration {
        TAILQ_ENTRY(netmsg_port_registration) npr_entry;
@@ -443,11 +444,24 @@ netisr_register(int num, netisr_fn_t handler, netisr_cpufn_t cpufn)
        ni = &netisrs[num];
 
        ni->ni_handler = handler;
        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
        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)
 {
        struct netmsg_rollup *ru;
 netisr_register_rollup(netisr_ru_t ru_func)
 {
        struct netmsg_rollup *ru;
@@ -663,3 +677,27 @@ netisr_barrier_rem(struct netisr_barrier *br)
 #endif
        br->br_isset = 0;
 }
 #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);
+}
index b60ce5c..8126176 100644 (file)
@@ -151,7 +151,7 @@ struct pktinfo {
  */
 struct netisr {
        netisr_fn_t     ni_handler;     /* packet handler function */
  */
 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) */
 };
        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);
 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_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);
 int            netisr_queue(int, struct mbuf *);
 
 struct netisr_barrier *netisr_barrier_create(void);
index 5e68985..6e98259 100644 (file)
 #include <sys/protosw.h>
 #endif
 
 #include <sys/protosw.h>
 #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_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)
 
 
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
index ac7894c..092adcb 100644 (file)
@@ -325,22 +325,19 @@ ip_cpufn_in(struct mbuf **mptr, int hoff)
        ip_cpufn(mptr, hoff, IP_MPORT_IN);
 }
 
        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
  * 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.
  */
  *
  * 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));
 
        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;
         */
        if (pi->pi_flags & PKTINFO_FLAG_FRAG) {
                m->m_pkthdr.hash = 0;
-               return cpu_portfn(0);
+               return;
        }
 
        switch (pi->pi_l3proto) {
        case IPPROTO_TCP:
        }
 
        switch (pi->pi_l3proto) {
        case IPPROTO_TCP:
-               port = cpu_portfn(m->m_pkthdr.hash);
-               break;
-
        case IPPROTO_UDP:
        case IPPROTO_UDP:
-               port = cpu_portfn(m->m_pkthdr.hash);
                break;
 
        default:
                break;
 
        default:
-               port = NULL;
+               /* Let software calculate the hash */
+               m->m_flags &= ~M_HASH;
                break;
        }
                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
 /*
  * 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
index 0d277e7..095d180 100644 (file)
@@ -379,6 +379,7 @@ ip_init(void)
 #endif
 
        netisr_register(NETISR_IP, ip_input_handler, ip_cpufn_in);
 #endif
 
        netisr_register(NETISR_IP, ip_input_handler, ip_cpufn_in);
+       netisr_register_hashcheck(NETISR_IP, ip_hashcheck);
 }
 
 /* Do transport protocol processing. */
 }
 
 /* Do transport protocol processing. */
index e68e4c8..eb5afc6 100644 (file)
@@ -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_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);
 
 boolean_t
         ip_lengthcheck(struct mbuf **, int);