svn commit: r191694 - projects/pnet/sys/net
Robert Watson
rwatson at FreeBSD.org
Thu Apr 30 15:38:36 UTC 2009
Author: rwatson
Date: Thu Apr 30 15:38:35 2009
New Revision: 191694
URL: http://svn.freebsd.org/changeset/base/191694
Log:
Revise netisr2 interface some more:
- Add public APIs to query available workstream counts and CPU IDs for
them (netisr2_get_cpucount(), netisr2_get_cpuid()).
- Provide default flow2cpu inmplementation as netisr2_default_flow2cpu,
and install it if the protocol doesn't register one.
- Add uintptr_t source argument to netisr2_queue() and netisr2_dispatch(),
allowing to caller to provide additional information about a source that
might be used to improve parallelism by constraining ordering. Should
be set to 0 if none is identified (i.e., maximum ordering).
- If the protocol doesn't provide a flow ID conversion function and there
isn't one on the packet, use the source to order.
Modified:
projects/pnet/sys/net/netisr2.c
projects/pnet/sys/net/netisr2.h
Modified: projects/pnet/sys/net/netisr2.c
==============================================================================
--- projects/pnet/sys/net/netisr2.c Thu Apr 30 14:31:52 2009 (r191693)
+++ projects/pnet/sys/net/netisr2.c Thu Apr 30 15:38:35 2009 (r191694)
@@ -250,6 +250,37 @@ static u_int nws_count;
#define NWS_WAIT(s) cv_wait(&(s)->nws_cv, &(s)->nws_mtx)
/*
+ * Utility routines for protocols that implement their own mapping of flows
+ * to CPUs.
+ */
+u_int
+netisr2_get_cpucount(void)
+{
+
+ return (nws_count);
+}
+
+u_int
+netisr2_get_cpuid(u_int cpunumber)
+{
+
+ return (nws_array[cpunumber]);
+}
+
+/*
+ * The default implementation of (source, flow ID) -> CPU ID mapping.
+ * Non-static so that protocols can use it to map their own work to specific
+ * CPUs in a manner consistent to netisr2 for affinity purposes.
+ */
+u_int
+netisr2_default_flow2cpu(uintptr_t source, u_int flowid)
+{
+
+ return (netisr2_get_cpuid((source ^ flowid) %
+ netisr2_get_cpucount()));
+}
+
+/*
* Register a new netisr handler, which requires initializing per-protocol
* fields for each workstream. All netisr2 work is briefly suspended while
* the protocol is installed.
@@ -275,10 +306,6 @@ netisr2_register(u_int proto, const char
KASSERT(name != NULL, ("netisr2_register: name NULL for %d", proto));
KASSERT(func != NULL, ("netisr2_register: func NULL for %s", name));
- KASSERT(m2flow != NULL, ("netisr2_register: m2flow NULL for %s",
- name));
- KASSERT(flow2cpu != NULL, ("netisr2_registeR: flow2cpu NULL for %s",
- name));
/*
* Initialize global and per-workstream protocol state.
@@ -286,7 +313,10 @@ netisr2_register(u_int proto, const char
np[proto].np_name = name;
np[proto].np_func = func;
np[proto].np_m2flow = m2flow;
- np[proto].np_flow2cpu = flow2cpu;
+ if (flow2cpu != NULL)
+ np[proto].np_flow2cpu = flow2cpu;
+ else
+ np[proto].np_flow2cpu = netisr2_default_flow2cpu;
for (i = 0; i < MAXCPU; i++) {
npwp = &nws[i].nws_work[proto];
bzero(npwp, sizeof(*npwp));
@@ -346,17 +376,6 @@ netisr2_deregister(u_int proto)
}
/*
- * Provide a simple flow -> CPU mapping for protocols with strong ordering
- * requirements but no built-in notion of affinity.
- */
-u_int
-netisr2_flowid2cpuid(u_int flowid)
-{
-
- return (nws_array[flowid % nws_count]);
-}
-
-/*
* Look up the correct stream for a requested flowid. There are two cases:
* one in which the caller has requested execution on the current CPU (i.e.,
* source ordering is sufficient, perhaps because the underlying hardware has
@@ -372,12 +391,13 @@ netisr2_flowid2cpuid(u_int flowid)
* (i.e., out of mbufs and a rewrite is required).
*/
static struct mbuf *
-netisr2_selectcpu(struct netisr_proto *npp, struct mbuf *m, u_int *cpuidp)
+netisr2_selectcpu(struct netisr_proto *npp, uintptr_t source, struct mbuf *m,
+ u_int *cpuidp)
{
NETISR_LOCK_ASSERT();
- if (!(m->m_flags & M_FLOWID)) {
+ if (!(m->m_flags & M_FLOWID) && npp->np_m2flow != NULL) {
m = npp->np_m2flow(m);
if (m == NULL)
return (NULL);
@@ -385,7 +405,10 @@ netisr2_selectcpu(struct netisr_proto *n
" %s failed to return flowid on mbuf",
npp->np_name));
}
- *cpuidp = npp->np_flow2cpu(m->m_pkthdr.flowid);
+ if (m->m_flags & M_FLOWID)
+ *cpuidp = npp->np_flow2cpu(source, m->m_pkthdr.flowid);
+ else
+ *cpuidp = npp->np_flow2cpu(source, 0);
return (m);
}
@@ -554,7 +577,7 @@ netisr2_queue_internal(u_int proto, stru
}
int
-netisr2_queue(u_int proto, struct mbuf *m)
+netisr2_queue(u_int proto, uintptr_t source, struct mbuf *m)
{
u_int cpuid, error;
@@ -565,7 +588,7 @@ netisr2_queue(u_int proto, struct mbuf *
KASSERT(np[proto].np_func != NULL,
("netisr2_dispatch: invalid proto %d", proto));
- m = netisr2_selectcpu(&np[proto], m, &cpuid);
+ m = netisr2_selectcpu(&np[proto], source, m, &cpuid);
if (m != NULL)
error = netisr2_queue_internal(proto, m, cpuid);
else
@@ -575,13 +598,13 @@ netisr2_queue(u_int proto, struct mbuf *
}
int
-netisr2_dispatch(u_int proto, struct mbuf *m)
+netisr2_dispatch(u_int proto, uintptr_t source, struct mbuf *m)
{
struct netisr_workstream *nwsp;
struct netisr_work *npwp;
if (!netisr_direct)
- return (netisr2_queue(proto, m));
+ return (netisr2_queue(proto, source, m));
KASSERT(proto < NETISR_MAXPROT,
("netisr2_dispatch: invalid proto %d", proto));
Modified: projects/pnet/sys/net/netisr2.h
==============================================================================
--- projects/pnet/sys/net/netisr2.h Thu Apr 30 14:31:52 2009 (r191693)
+++ projects/pnet/sys/net/netisr2.h Thu Apr 30 15:38:35 2009 (r191694)
@@ -43,14 +43,16 @@
* NULL should be returned.
*
* netisr_flow2cpu_t - Given a flowid, possibly generated by netisr_m2flow,
- * select a CPU to execute the packet handler on.
+ * and an optional source identifier (possibly a tid, pcb,
+ * or kernel pointer), select a CPU to execute the packet
+ * handler on. If source isn't used, it will be 0/NULL.
*
* XXXRW: If we eventually support dynamic reconfiguration, there should be
* protocol handlers to notify them of CPU configuration changes so that they
* can rebalance work.
*/
typedef struct mbuf *netisr_m2flow_t(struct mbuf *m);
-typedef u_int netisr_flow2cpu_t(u_int flowid);
+typedef u_int netisr_flow2cpu_t(uintptr_t source, u_int flowid);
/*-
* Register a new netisr2 handler for a given protocol. No previous
@@ -74,16 +76,20 @@ void netisr2_deregister(u_int proto);
/*
* Process a packet destined for a protocol, and attempt direct dispatch.
*/
-int netisr2_dispatch(u_int proto, struct mbuf *m);
-int netisr2_queue(u_int proto, struct mbuf *m);
+int netisr2_dispatch(u_int proto, uintptr_t source, struct mbuf *m);
+int netisr2_queue(u_int proto, uintptr_t source, struct mbuf *m);
/*
- * Provide a default function to map flow IDs to CPU IDs, so that protocols
- * needing a default flow->CPU model can use it.
- *
- * XXXRW: Should also provide a way to query available CPUs so that protocols
- * can decide how to map work more usefully themselves.
+ * Provide a default implementation of "map a flow ID to a cpu ID".
+ */
+u_int netisr2_default_flow2cpu(uintptr_t source, u_int flowid);
+
+/*
+ * Utility routines to return the number of CPUs participting in netisr2, and
+ * to return a mapping from a number to a CPU ID that can be used with the
+ * scheduler.
*/
-u_int netisr2_flowid2cpuid(u_int flowid);
+u_int netisr2_get_cpucount(void);
+u_int netisr2_get_cpuid(u_int cpunumber);
#endif /* !_NET_NETISR2_H_ */
More information about the svn-src-projects
mailing list