Page MenuHomeFreeBSD

D1987.vs4030.id4032.diff
No OneTemporary

D1987.vs4030.id4032.diff

Index: share/man/man9/Makefile
===================================================================
--- share/man/man9/Makefile
+++ share/man/man9/Makefile
@@ -1558,6 +1558,7 @@
timeout.9 callout_active.9 \
timeout.9 callout_deactivate.9 \
timeout.9 callout_drain.9 \
+ timeout.9 callout_drain_async.9 \
timeout.9 callout_handle_init.9 \
timeout.9 callout_init.9 \
timeout.9 callout_init_mtx.9 \
Index: share/man/man9/timeout.9
===================================================================
--- share/man/man9/timeout.9
+++ share/man/man9/timeout.9
@@ -29,13 +29,14 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 8, 2014
+.Dd January 24, 2015
.Dt TIMEOUT 9
.Os
.Sh NAME
.Nm callout_active ,
.Nm callout_deactivate ,
.Nm callout_drain ,
+.Nm callout_drain_async ,
.Nm callout_handle_init ,
.Nm callout_init ,
.Nm callout_init_mtx ,
@@ -63,256 +64,234 @@
.In sys/systm.h
.Bd -literal
typedef void timeout_t (void *);
+typedef void callout_func_t (void *);
.Ed
-.Ft int
-.Fn callout_active "struct callout *c"
-.Ft void
-.Fn callout_deactivate "struct callout *c"
-.Ft int
-.Fn callout_drain "struct callout *c"
-.Ft void
-.Fn callout_handle_init "struct callout_handle *handle"
-.Bd -literal
-struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
-.Ed
-.Ft void
-.Fn callout_init "struct callout *c" "int mpsafe"
-.Ft void
-.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
-.Ft void
-.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
-.Ft void
-.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
-.Ft int
-.Fn callout_pending "struct callout *c"
-.Ft int
-.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
-.Ft int
-.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
-"void *arg"
-.Ft int
-.Fn callout_reset_on "struct callout *c" "int ticks" "timeout_t *func" \
-"void *arg" "int cpu"
-.Ft int
-.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
-.Ft int
-.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
-.Ft int
-.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "timeout_t *func" "void *arg" "int cpu" "int flags"
-.Ft int
-.Fn callout_schedule "struct callout *c" "int ticks"
-.Ft int
-.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
-.Ft int
-.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
-.Ft int
-.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int flags"
-.Ft int
-.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int flags"
-.Ft int
-.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
-"sbintime_t pr" "int cpu" "int flags"
-.Ft int
-.Fn callout_stop "struct callout *c"
-.Ft struct callout_handle
-.Fn timeout "timeout_t *func" "void *arg" "int ticks"
-.Ft void
-.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
.Sh DESCRIPTION
The
.Nm callout
-API is used to schedule a call to an arbitrary function at a specific
-time in the future.
-Consumers of this API are required to allocate a callout structure
-.Pq struct callout
+API is used to schedule a one-time call to an arbitrary function at a
+specific time in the future.
+Consumers of this API are required to allocate a
+.Ft struct callout
for each pending function invocation.
-This structure stores state about the pending function invocation including
-the function to be called and the time at which the function should be invoked.
-Pending function calls can be cancelled or rescheduled to a different time.
-In addition,
-a callout structure may be reused to schedule a new function call after a
-scheduled call is completed.
-.Pp
-Callouts only provide a single-shot mode.
-If a consumer requires a periodic timer,
-it must explicitly reschedule each function call.
-This is normally done by rescheduling the subsequent call within the called
-function.
-.Pp
-Callout functions must not sleep.
-They may not acquire sleepable locks,
-wait on condition variables,
-perform blocking allocation requests,
-or invoke any other action that might sleep.
-.Pp
-Each callout structure must be initialized by
-.Fn callout_init ,
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-or
-.Fn callout_init_rw
-before it is passed to any of the other callout functions.
The
+.Ft struct callout
+stores the full state about any pending function call and
+must be drained by a call to
+.Fn callout_drain
+or
+.Fn callout_drain_async
+before freeing.
+.Sh INITIALIZATION
+.Ft void
+.Fn callout_handle_init "struct callout_handle *handle"
+This function is deprecated.
+Please use
.Fn callout_init
-function initializes a callout structure in
-.Fa c
-that is not associated with a specific lock.
+instead.
+This function is used to prepare a
+.Ft struct callout_handle
+before it can be used the first time.
+If this function is called on a pending timeout, the pending timeout
+cannot be cancelled and the
+.Fn untimeout
+function will return as if no timeout was pending.
+.Pp
+.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
+This macro is deprecated.
+This macro is used to statically initialize a
+.Ft struct callout_handle .
+Please use
+.Fn callout_init
+instead.
+.Pp
+.Ft void
+.Fn callout_init "struct callout *c" "int mpsafe"
+This function prepares a
+.Ft struct callout
+before it can be used.
+This function should not be used when the callout is pending a timeout.
If the
.Fa mpsafe
-argument is zero,
-the callout structure is not considered to be
-.Dq multi-processor safe ;
-and the Giant lock will be acquired before calling the callout function
-and released when the callout function returns.
-.Pp
-The
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-and
-.Fn callout_init_rw
-functions initialize a callout structure in
-.Fa c
-that is associated with a specific lock.
-The lock is specified by the
-.Fa mtx ,
-.Fa rm ,
-or
-.Fa rw
-parameter.
-The associated lock must be held while stopping or rescheduling the
-callout.
-The callout subsystem acquires the associated lock before calling the
-callout function and releases it after the function returns.
-If the callout was cancelled while the callout subsystem waited for the
-associated lock,
-the callout function is not called,
-and the associated lock is released.
-This ensures that stopping or rescheduling the callout will abort any
-previously scheduled invocation.
-.Pp
-Only regular mutexes may be used with
-.Fn callout_init_mtx ;
-spin mutexes are not supported.
-A sleepable read-mostly lock
-.Po
-one initialized with the
-.Dv RM_SLEEPABLE
-flag
-.Pc
-may not be used with
-.Fn callout_init_rm .
-Similarly, other sleepable lock types such as
-.Xr sx 9
-and
-.Xr lockmgr 9
-cannot be used with callouts because sleeping is not permitted in
-the callout subsystem.
+argument is non-zero, the callback function will be running unlocked
+and the callback is so-called "mpsafe".
+.Bf Sy
+It is the application's entire responsibility to not call any
+.Fn callout_xxx
+functions, including the
+.Fn callout_drain
+function, simultaneously on the same callout when the
+.Fa mpsafe
+argument is non-zero.
+Otherwise, undefined behavior can happen.
+Avoid simultaneous calls by obtaining an exclusive lock before calling
+any
+.Fn callout_xxx
+functions other than the
+.Fn callout_drain
+function.
+.Ef
+If the
+.Fa mpsafe
+argument is zero, the Giant mutex will be locked before the callback
+function is called.
+If the
+.Fa mpsafe
+argument is zero, the Giant mutex is expected to be locked when calling
+any
+.Fn callout_xxx
+functions which start and stop a callout other than the
+.Fn callout_drain
+function.
.Pp
-These
+.Ft void
+.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
+This function prepares a
+.Ft struct callout
+before it can be used.
+This function should not be used when the callout is pending a timeout.
+The
+.Fa mtx
+argument is a pointer to a valid spinlock type of mutex or a valid
+regular non-sleepable mutex which the callback subsystem will lock
+before calling the callback function.
+The specified mutex is expected to be locked when calling any
+.Fn callout_xxx
+functions which start and stop a callout other than the
+.Fn callout_drain
+function.
+Valid
.Fa flags
-may be specified for
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-or
-.Fn callout_init_rw :
+are:
.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
.It Dv CALLOUT_RETURNUNLOCKED
-The callout function will release the associated lock itself,
-so the callout subsystem should not attempt to unlock it
-after the callout function returns.
-.It Dv CALLOUT_SHAREDLOCK
-The lock is only acquired in read mode when running the callout handler.
-This flag is ignored by
-.Fn callout_init_mtx .
+The callout function is assumed to have released the specified mutex
+before returning.
+.It Dv 0
+The callout subsystem will release the specified mutex after the
+callout function has returned.
.El
.Pp
-The function
-.Fn callout_stop
-cancels a callout
-.Fa c
-if it is currently pending.
-If the callout is pending, then
-.Fn callout_stop
-returns a non-zero value.
-If the callout is not set,
-has already been serviced,
-or is currently being serviced,
-then zero will be returned.
-If the callout has an associated lock,
-then that lock must be held when this function is called.
-.Pp
-The function
-.Fn callout_drain
-is identical to
-.Fn callout_stop
-except that it will wait for the callout
-.Fa c
-to complete if it is already in progress.
-This function MUST NOT be called while holding any
-locks on which the callout might block, or deadlock will result.
-Note that if the callout subsystem has already begun processing this
-callout, then the callout function may be invoked before
-.Fn callout_drain
-returns.
-However, the callout subsystem does guarantee that the callout will be
-fully stopped before
-.Fn callout_drain
-returns.
+.Ft void
+.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
+This function is similar to
+.Fn callout_init_mtx ,
+but it accepts a read-mostly type of lock.
+The read-mostly lock must not be initialized with the
+.Dv RM_SLEEPABLE
+flag.
.Pp
-The
+.Ft void
+.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
+This function is similar to
+.Fn callout_init_mtx ,
+but it accepts a read/write type of lock.
+.Sh SCHEDULING CALLOUTS
+.Ft struct callout_handle
+.Fn timeout "timeout_t *func" "void *arg" "int ticks"
+This function is deprecated.
+Please use
.Fn callout_reset
-and
-.Fn callout_schedule
-function families schedule a future function invocation for callout
-.Fa c .
-If
-.Fa c
-already has a pending callout,
-it is cancelled before the new invocation is scheduled.
-These functions return a non-zero value if a pending callout was cancelled
-and zero if there was no pending callout.
-If the callout has an associated lock,
-then that lock must be held when any of these functions are called.
-.Pp
-The time at which the callout function will be invoked is determined by
-either the
-.Fa ticks
-argument or the
-.Fa sbt ,
-.Fa pr ,
-and
-.Fa flags
-arguments.
-When
-.Fa ticks
-is used,
-the callout is scheduled to execute after
+instead.
+This function schedules a call to
+.Fa func
+to take place after
.Fa ticks Ns No /hz
seconds.
Non-positive values of
.Fa ticks
are silently converted to the value
.Sq 1 .
-.Pp
The
-.Fa sbt ,
-.Fa pr ,
-and
-.Fa flags
-arguments provide more control over the scheduled time including
-support for higher resolution times,
-specifying the precision of the scheduled time,
-and setting an absolute deadline instead of a relative timeout.
-The callout is scheduled to execute in a time window which begins at
-the time specified in
+.Fa func
+argument is a valid pointer to a function that takes a single
+.Fa void *
+argument.
+Upon invocation, the
+.Fa func
+function will receive
+.Fa arg
+as its only argument.
+The Giant lock is locked when the
+.Fa arg
+function is invoked and should not be unlocked by this function.
+The returned value from
+.Fn timeout
+is a
+.Ft struct callout_handle
+structure which can be used in conjunction with the
+.Fn untimeout
+function to request that a scheduled timeout be cancelled.
+As handles are recycled by the system, it is possible, although unlikely,
+that a handle from one invocation of
+.Fn timeout
+may match the handle of another invocation of
+.Fn timeout
+if both calls used the same function pointer and argument, and the first
+timeout is expired or cancelled before the second call.
+Please ensure that the function and argument pointers are unique when using this function.
+.Pp
+.Ft int
+.Fn callout_reset "struct callout *c" "int ticks" "callout_func_t *func" "void *arg"
+This function is used to schedule or re-schedule a callout.
+This function at first stops the callout given by the
+.Fa c
+argument, if any.
+Then it will start the callout given by the
+.Fa c
+argument.
+The relative time until the timeout callback happens is given by the
+.Fa ticks
+argument.
+The number of ticks in a second is defined by
+.Dv hz
+and can vary from system to system.
+This function returns a non-zero value if the given callout was pending and
+the callback function was prevented from being called.
+Otherwise, a value of zero is returned.
+If a lock is associated with the callout given by the
+.Fa c
+argument and it is exclusivly locked when this function is called, this
+function will always ensure that previous callback function, if any,
+is never reached.
+In other words, the callout will be atomically restarted.
+Otherwise, there is no such guarantee.
+The callback function is given by
+.Fa func
+and its function argument is given by
+.Fa arg .
+.Pp
+.Ft int
+.Fn callout_reset_curcpu "struct callout *c" "int ticks" "callout_func_t *func" \
+"void *arg"
+This function works the same like the
+.Fn callout_reset
+function except the callback function given by the
+.Fa func
+argument will be executed on the same CPU which called this function.
+.Pp
+.Ft int
+.Fn callout_reset_on "struct callout *c" "int ticks" "callout_func_t *func" \
+"void *arg" "int cpu"
+This function works the same like the
+.Fn callout_reset
+function except the callback function given by the
+.Fa func
+argument will be executed on the CPU given by the
+.Fa cpu
+argument.
+.Pp
+.Ft int
+.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "callout_func_t *func" "void *arg" "int flags"
+This function works the same like the
+.Fn callout_reset
+function except the relative or absolute time after which the timeout
+callback should happen is given by the
.Fa sbt
-and extends for the amount of time specified in
+argument and extends for the amount of time specified in
.Fa pr .
+This function is used when high precision timeouts are needed.
If
.Fa sbt
specifies a time in the past,
@@ -322,12 +301,13 @@
allows the callout subsystem to coalesce callouts scheduled close to each
other into fewer timer interrupts,
reducing processing overhead and power consumption.
-These
+The
.Fa flags
-may be specified to adjust the interpretation of
+argument may be non-zero to adjust the interpretation of the
.Fa sbt
and
-.Fa pr :
+.Fa pr
+arguments:
.Bl -tag -width ".Dv C_DIRECT_EXEC"
.It Dv C_ABSOLUTE
Handle the
@@ -347,7 +327,7 @@
and should be as small as possible because they run with absolute priority.
.It Fn C_PREL
Specifies relative event time precision as binary logarithm of time interval
-divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, etc.
+divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, and so on.
Note that the larger of
.Fa pr
or this value is used as the length of the time window.
@@ -360,65 +340,207 @@
calls if possible.
.El
.Pp
-The
-.Fn callout_reset
-functions accept a
+.Ft int
+.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "callout_func_t *func" "void *arg" "int flags"
+This function works like
+.Fn callout_reset_sbt ,
+except the callback function given by the
.Fa func
-argument which identifies the function to be called when the time expires.
-It must be a pointer to a function that takes a single
-.Fa void *
-argument.
-Upon invocation,
+argument will be executed on the CPU which called this function.
+.Pp
+.Ft int
+.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "callout_func_t *func" "void *arg" "int cpu" "int flags"
+This function works like
+.Fn callout_reset_sbt ,
+except the callback function given by
.Fa func
-will receive
-.Fa arg
-as its only argument.
-The
-.Fn callout_schedule
-functions reuse the
+will be executed on the CPU given by
+.Fa cpu .
+.Pp
+.Ft int
+.Fn callout_schedule "struct callout *c" "int ticks"
+This function works the same like the
+.Fn callout_reset
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Pp
+.Ft int
+.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
+This function works the same like the
+.Fn callout_reset_curcpu
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Pp
+.Ft int
+.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
+This function works the same like the
+.Fn callout_reset_on
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Pp
+.Ft int
+.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "int flags"
+This function works the same like the
+.Fn callout_reset_sbt
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Pp
+.Ft int
+.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "int flags"
+This function works the same like the
+.Fn callout_reset_sbt_curcpu
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Pp
+.Ft int
+.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
+"sbintime_t pr" "int cpu" "int flags"
+This function works the same like the
+.Fn callout_reset_sbt_on
+function except it re-uses the callback function and the callback argument
+already stored in the
+.Pq struct callout
+structure.
+.Sh CHECKING THE STATE OF CALLOUTS
+.Ft int
+.Fn callout_pending "struct callout *c"
+This function returns non-zero if the callout pointed to by the
+.Fa c
+argument is pending for callback.
+Else this function returns zero.
+This function returns zero when inside the callout function if the
+callout is not re-scheduled.
+.Pp
+.Ft int
+.Fn callout_active "struct callout *c"
+This function is deprecated and returns non-zero if the callout
+pointed to by the
+.Fa c
+argument was scheduled in the past.
+Else this function returns zero.
+This function also returns zero after the
+.Fn callout_deactivate
+or the
+.Fn callout_stop
+or the
+.Fn callout_drain
+or the
+.Fn callout_drain_async
+function is called on the same callout as given by the
+.Fa c
+argument.
+.Pp
+.Ft void
+.Fn callout_deactivate "struct callout *c"
+This function is deprecated and ensures that subsequent calls to the
+.Fn callout_activate
+function returns zero until the callout is scheduled again.
+.Sh STOPPING CALLOUTS
+.Ft void
+.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
+This function is deprecated and cancels the timeout associated with the
+.Fa handle
+argument using the function pointed to by the
.Fa func
-and
+argument and having the
.Fa arg
-arguments from the previous callout.
-Note that one of the
-.Fn callout_reset
-functions must always be called to initialize
+arguments to validate the handle.
+If the handle does not correspond to a timeout with
+the function
.Fa func
-and
+taking the argument
.Fa arg
-before one of the
-.Fn callout_schedule
-functions can be used.
+no action is taken. The
+.Fa handle
+must be initialized by a previous call to
+.Fn timeout ,
+.Fn callout_handle_init
+or assigned the value of
+.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
+before being passed to
+.Fn untimeout .
+The behavior of calling
+.Fn untimeout
+with an uninitialized handle
+is undefined.
.Pp
-The callout subsystem provides a softclock thread for each CPU in the system.
-Callouts are assigned to a single CPU and are executed by the softclock thread
-for that CPU.
-Initially,
-callouts are assigned to CPU 0.
-The
-.Fn callout_reset_on ,
-.Fn callout_reset_sbt_on ,
-.Fn callout_schedule_on
-and
-.Fn callout_schedule_sbt_on
-functions assign the callout to CPU
-.Fa cpu .
-The
-.Fn callout_reset_curcpu ,
-.Fn callout_reset_sbt_curpu ,
-.Fn callout_schedule_curcpu
-and
-.Fn callout_schedule_sbt_curcpu
-functions assign the callout to the current CPU.
-The
-.Fn callout_reset ,
-.Fn callout_reset_sbt ,
-.Fn callout_schedule
-and
-.Fn callout_schedule_sbt
-functions schedule the callout to execute in the softclock thread of the CPU
-to which it is currently assigned.
+.Ft int
+.Fn callout_stop "struct callout *c"
+This function is used to stop a timeout function invocation associated with the callout pointed to by the
+.Fa c
+argument, in a non-blocking fashion.
+This function can be called multiple times in a row with no side effects, even if the callout is already stopped. This function however should not be called before the callout has been initialized.
+This function returns a non-zero value if the given callout was pending and
+the callback function was prevented from being called.
+Else a value of zero is returned.
+If a lock is associated with the callout given by the
+.Fa c
+argument and it is exclusivly locked when this function is called, the
+.Fn callout_stop
+function will always ensure that the callback function is never reached.
+In other words the callout will be atomically stopped.
+Else there is no such guarantee.
+.Sh DRAINING CALLOUTS
+.Ft int
+.Fn callout_drain "struct callout *c"
+This function works the same like the
+.Fn callout_stop
+function except it ensures that all callback functions have returned and there are no more references to the callout pointed to by the
+.Fa c
+argument inside the callout subsystem before it returns.
+Also this function ensures that the lock, if any, associated with the
+callout is no longer being used.
+When this function returns, it is safe to free the callout structure pointed to by the
+.Fa c
+argument.
.Pp
+.Ft int
+.Fn callout_drain_async "struct callout *c" "callout_func_t *fn" "void *arg"
+This function is non-blocking and works the same like the
+.Fn callout_stop
+function except if it returns non-zero it means the callback function pointed to by the
+.Fa fn
+argument will be called back with the
+.Fa arg
+argument when all references to the callout pointed to by the
+.Fa c
+argument are gone.
+If this function returns non-zero it should not be called again until the callback function has been called.
+If the
+.Fn callout_drain
+or
+.Fn callout_drain_async
+functions are called while an asynchronous drain is pending,
+previously pending asynchronous drains might get cancelled.
+If this function returns zero, it is safe to free the callout structure pointed to by the
+.Fa c
+argument right away.
+.Sh CALLOUT FUNCTION RESTRICTIONS
+Callout functions must not sleep.
+They may not acquire sleepable locks, wait on condition variables,
+perform blocking allocation requests, or invoke any other action that
+might sleep.
+.Sh CALLOUT SUBSYSTEM INTERNALS
+The callout subsystem has its own set of spinlocks to protect its internal state.
+The callout subsystem provides a softclock thread for each CPU in the
+system.
+Callouts are assigned to a single CPU and are executed by the
+softclock thread for that CPU.
+Initially, callouts are assigned to CPU 0.
Softclock threads are not pinned to their respective CPUs by default.
The softclock thread for CPU 0 can be pinned to CPU 0 by setting the
.Va kern.pin_default_swi
@@ -427,50 +549,7 @@
respective CPUs by setting the
.Va kern.pin_pcpu_swi
loader tunable to a non-zero value.
-.Pp
-The macros
-.Fn callout_pending ,
-.Fn callout_active
-and
-.Fn callout_deactivate
-provide access to the current state of the callout.
-The
-.Fn callout_pending
-macro checks whether a callout is
-.Em pending ;
-a callout is considered
-.Em pending
-when a timeout has been set but the time has not yet arrived.
-Note that once the timeout time arrives and the callout subsystem
-starts to process this callout,
-.Fn callout_pending
-will return
-.Dv FALSE
-even though the callout function may not have finished
-.Pq or even begun
-executing.
-The
-.Fn callout_active
-macro checks whether a callout is marked as
-.Em active ,
-and the
-.Fn callout_deactivate
-macro clears the callout's
-.Em active
-flag.
-The callout subsystem marks a callout as
-.Em active
-when a timeout is set and it clears the
-.Em active
-flag in
-.Fn callout_stop
-and
-.Fn callout_drain ,
-but it
-.Em does not
-clear it when a callout expires normally via the execution of the
-callout function.
-.Ss "Avoiding Race Conditions"
+.Sh "AVOIDING RACE CONDITIONS"
The callout subsystem invokes callout functions from its own thread
context.
Without some kind of synchronization,
@@ -531,9 +610,8 @@
.Pc
indicates whether or not the callout was removed.
If it is known that the callout was set and the callout function has
-not yet executed, then a return value of
-.Dv FALSE
-indicates that the callout function is about to be called.
+not yet executed, then a return value of zero indicates that the
+callout function is about to be called.
For example:
.Bd -literal -offset indent
if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) {
@@ -589,16 +667,14 @@
.Em pending
flag and return without action if
.Fn callout_pending
-returns
-.Dv TRUE .
+returns non-zero.
This indicates that the callout was rescheduled using
.Fn callout_reset
just before the callout function was invoked.
If
.Fn callout_active
-returns
-.Dv FALSE
-then the callout function should also return without action.
+returns zero then the callout function should also return without
+action.
This indicates that the callout has been stopped.
Finally, the callout function should call
.Fn callout_deactivate
@@ -668,129 +744,13 @@
or releasing the storage for the callout structure.
.Sh LEGACY API
.Bf Sy
-The functions below are a legacy API that will be removed in a future release.
-New code should not use these routines.
-.Ef
-.Pp
-The function
-.Fn timeout
-schedules a call to the function given by the argument
-.Fa func
-to take place after
-.Fa ticks Ns No /hz
-seconds.
-Non-positive values of
-.Fa ticks
-are silently converted to the value
-.Sq 1 .
-.Fa func
-should be a pointer to a function that takes a
-.Fa void *
-argument.
-Upon invocation,
-.Fa func
-will receive
-.Fa arg
-as its only argument.
-The return value from
+The
.Fn timeout
-is a
-.Ft struct callout_handle
-which can be used in conjunction with the
-.Fn untimeout
-function to request that a scheduled timeout be canceled.
-.Pp
-The function
-.Fn callout_handle_init
-can be used to initialize a handle to a state which will cause
-any calls to
-.Fn untimeout
-with that handle to return with no side
-effects.
-.Pp
-Assigning a callout handle the value of
-.Fn CALLOUT_HANDLE_INITIALIZER
-performs the same function as
-.Fn callout_handle_init
-and is provided for use on statically declared or global callout handles.
-.Pp
-The function
-.Fn untimeout
-cancels the timeout associated with
-.Fa handle
-using the
-.Fa func
and
-.Fa arg
-arguments to validate the handle.
-If the handle does not correspond to a timeout with
-the function
-.Fa func
-taking the argument
-.Fa arg
-no action is taken.
-.Fa handle
-must be initialized by a previous call to
-.Fn timeout ,
-.Fn callout_handle_init ,
-or assigned the value of
-.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
-before being passed to
-.Fn untimeout .
-The behavior of calling
.Fn untimeout
-with an uninitialized handle
-is undefined.
-.Pp
-As handles are recycled by the system, it is possible (although unlikely)
-that a handle from one invocation of
-.Fn timeout
-may match the handle of another invocation of
-.Fn timeout
-if both calls used the same function pointer and argument, and the first
-timeout is expired or canceled before the second call.
-The timeout facility offers O(1) running time for
-.Fn timeout
-and
-.Fn untimeout .
-Timeouts are executed from
-.Fn softclock
-with the
-.Va Giant
-lock held.
-Thus they are protected from re-entrancy.
-.Sh RETURN VALUES
-The
-.Fn callout_active
-macro returns the state of a callout's
-.Em active
-flag.
-.Pp
-The
-.Fn callout_pending
-macro returns the state of a callout's
-.Em pending
-flag.
-.Pp
-The
-.Fn callout_reset
-and
-.Fn callout_schedule
-function families return non-zero if the callout was pending before the new
-function invocation was scheduled.
-.Pp
-The
-.Fn callout_stop
-and
-.Fn callout_drain
-functions return non-zero if the callout was still pending when it was
-called or zero otherwise.
-The
-.Fn timeout
-function returns a
-.Ft struct callout_handle
-that can be passed to
-.Fn untimeout .
+functions are a legacy API that will be removed in a future release.
+New code should not use these routines.
+.Ef
.Sh HISTORY
The current timeout and untimeout routines are based on the work of
.An Adam M. Costello
@@ -815,4 +775,4 @@
.Bx
linked list
callout mechanism which offered O(n) insertion and removal running time
-but did not generate or require handles for untimeout operations.
+and did not generate or require handles for untimeout operations.
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3102,6 +3102,7 @@
kern/uipc_domain.c standard
kern/uipc_mbuf.c standard
kern/uipc_mbuf2.c standard
+kern/uipc_mbufhash.c standard
kern/uipc_mqueue.c optional p1003_1b_mqueue
kern/uipc_sem.c optional p1003_1b_semaphores
kern/uipc_shm.c standard
Index: sys/kern/uipc_mbufhash.c
===================================================================
--- sys/kern/uipc_mbufhash.c
+++ sys/kern/uipc_mbufhash.c
@@ -25,57 +25,32 @@
#include <sys/param.h>
#include <sys/kernel.h>
-#include <sys/malloc.h>
#include <sys/mbuf.h>
-#include <sys/queue.h>
+#include <sys/fnv_hash.h>
#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/module.h>
-#include <sys/priv.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/hash.h>
-#include <sys/lock.h>
-#include <sys/rmlock.h>
-#include <sys/taskqueue.h>
-#include <sys/eventhandler.h>
-#include <net/ethernet.h>
#include <net/if.h>
-#include <net/if_clone.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_llc.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
#include <net/if_var.h>
-#include <net/bpf.h>
+
+#include <net/ethernet.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
#endif
+
#ifdef INET
-#include <netinet/in_systm.h>
-#include <netinet/if_ether.h>
#include <netinet/ip.h>
#endif
#ifdef INET6
#include <netinet/ip6.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/in6_ifattach.h>
#endif
#include <net/if_vlan_var.h>
-#include "utils.h"
-
-/* XXX this code should be factored out */
-/* XXX copied from if_lagg.c */
-
static const void *
-mlx4_en_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
+m_ether_tcpip_hash_gethdr(const struct mbuf *m, const u_int off,
+ const u_int len, void *buf)
{
if (m->m_pkthdr.len < (off + len)) {
return (NULL);
@@ -87,7 +62,17 @@
}
uint32_t
-mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key)
+m_ether_tcpip_hash_init(void)
+{
+ uint32_t seed;
+
+ seed = arc4random();
+ return (fnv_32_buf(&seed, sizeof(seed), FNV1_32_INIT));
+}
+
+uint32_t
+m_ether_tcpip_hash(const uint32_t flags, const struct mbuf *m,
+ const uint32_t key)
{
uint16_t etype;
uint32_t p = key;
@@ -96,12 +81,9 @@
const struct ether_vlan_header *vlan;
#ifdef INET
const struct ip *ip;
- const uint32_t *ports;
- int iphlen;
#endif
#ifdef INET6
const struct ip6_hdr *ip6;
- uint32_t flow;
#endif
union {
#ifdef INET
@@ -112,48 +94,47 @@
#endif
struct ether_vlan_header vlan;
uint32_t port;
- } buf;
+ } buf;
off = sizeof(*eh);
if (m->m_len < off)
- goto out;
+ goto done;
eh = mtod(m, struct ether_header *);
etype = ntohs(eh->ether_type);
- if (flags & MLX4_F_HASHL2) {
- p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
- p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
+ if (flags & MBUF_HASHFLAG_L2) {
+ p = fnv_32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
+ p = fnv_32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
}
-
/* Special handling for encapsulating VLAN frames */
- if ((m->m_flags & M_VLANTAG) && (flags & MLX4_F_HASHL2)) {
- p = hash32_buf(&m->m_pkthdr.ether_vtag,
+ if ((m->m_flags & M_VLANTAG) && (flags & MBUF_HASHFLAG_L2)) {
+ p = fnv_32_buf(&m->m_pkthdr.ether_vtag,
sizeof(m->m_pkthdr.ether_vtag), p);
} else if (etype == ETHERTYPE_VLAN) {
- vlan = mlx4_en_gethdr(m, off, sizeof(*vlan), &buf);
+ vlan = m_ether_tcpip_hash_gethdr(m, off, sizeof(*vlan), &buf);
if (vlan == NULL)
- goto out;
+ goto done;
- if (flags & MLX4_F_HASHL2)
- p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
+ if (flags & MBUF_HASHFLAG_L2)
+ p = fnv_32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
etype = ntohs(vlan->evl_proto);
off += sizeof(*vlan) - sizeof(*eh);
}
-
switch (etype) {
#ifdef INET
case ETHERTYPE_IP:
- ip = mlx4_en_gethdr(m, off, sizeof(*ip), &buf);
+ ip = m_ether_tcpip_hash_gethdr(m, off, sizeof(*ip), &buf);
if (ip == NULL)
- goto out;
-
- if (flags & MLX4_F_HASHL3) {
- p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
- p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
- }
- if (!(flags & MLX4_F_HASHL4))
break;
- switch (ip->ip_p) {
+ if (flags & MBUF_HASHFLAG_L3) {
+ p = fnv_32_buf(&ip->ip_src, sizeof(struct in_addr), p);
+ p = fnv_32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
+ }
+ if (flags & MBUF_HASHFLAG_L4) {
+ const uint32_t *ports;
+ int iphlen;
+
+ switch (ip->ip_p) {
case IPPROTO_TCP:
case IPPROTO_UDP:
case IPPROTO_SCTP:
@@ -161,29 +142,37 @@
if (iphlen < sizeof(*ip))
break;
off += iphlen;
- ports = mlx4_en_gethdr(m, off, sizeof(*ports), &buf);
+ ports = m_ether_tcpip_hash_gethdr(m,
+ off, sizeof(*ports), &buf);
if (ports == NULL)
break;
- p = hash32_buf(ports, sizeof(*ports), p);
+ p = fnv_32_buf(ports, sizeof(*ports), p);
break;
+ }
}
break;
#endif
#ifdef INET6
case ETHERTYPE_IPV6:
- if (!(flags & MLX4_F_HASHL3))
- break;
- ip6 = mlx4_en_gethdr(m, off, sizeof(*ip6), &buf);
+ ip6 = m_ether_tcpip_hash_gethdr(m, off, sizeof(*ip6), &buf);
if (ip6 == NULL)
- goto out;
+ break;
+ if (flags & MBUF_HASHFLAG_L3) {
+ p = fnv_32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
+ p = fnv_32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
+ }
+ if (flags & MBUF_HASHFLAG_L4) {
+ uint32_t flow;
- p = hash32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
- p = hash32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
- flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
- p = hash32_buf(&flow, sizeof(flow), p); /* IPv6 flow label */
+ /* IPv6 flow label */
+ flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
+ p = fnv_32_buf(&flow, sizeof(flow), p);
+ }
break;
#endif
+ default:
+ break;
}
-out:
+done:
return (p);
}
Index: sys/net/if_lagg.c
===================================================================
--- sys/net/if_lagg.c
+++ sys/net/if_lagg.c
@@ -36,7 +36,6 @@
#include <sys/priv.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#include <sys/fnv_hash.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/taskqueue.h>
@@ -131,7 +130,6 @@
static void lagg_media_status(struct ifnet *, struct ifmediareq *);
static struct lagg_port *lagg_link_active(struct lagg_softc *,
struct lagg_port *);
-static const void *lagg_gethdr(struct mbuf *, u_int, u_int, void *);
/* Simple round robin */
static void lagg_rr_attach(struct lagg_softc *);
@@ -490,7 +488,7 @@
sc->flowid_shift = V_def_flowid_shift;
/* Hash all layers by default */
- sc->sc_flags = LAGG_F_HASHL2|LAGG_F_HASHL3|LAGG_F_HASHL4;
+ sc->sc_flags = MBUF_HASHFLAG_L2|MBUF_HASHFLAG_L3|MBUF_HASHFLAG_L4;
lagg_proto_attach(sc, LAGG_PROTO_DEFAULT);
@@ -1349,7 +1347,13 @@
LAGG_WUNLOCK(sc);
break;
case SIOCGLAGGFLAGS:
- rf->rf_flags = sc->sc_flags;
+ rf->rf_flags = 0;
+ if (sc->sc_flags & MBUF_HASHFLAG_L2)
+ rf->rf_flags |= LAGG_F_HASHL2;
+ if (sc->sc_flags & MBUF_HASHFLAG_L3)
+ rf->rf_flags |= LAGG_F_HASHL3;
+ if (sc->sc_flags & MBUF_HASHFLAG_L4)
+ rf->rf_flags |= LAGG_F_HASHL4;
break;
case SIOCSLAGGHASH:
error = priv_check(td, PRIV_NET_LAGG);
@@ -1360,8 +1364,13 @@
break;
}
LAGG_WLOCK(sc);
- sc->sc_flags &= ~LAGG_F_HASHMASK;
- sc->sc_flags |= rf->rf_flags & LAGG_F_HASHMASK;
+ sc->sc_flags &= ~MBUF_HASHFLAG_MASK;
+ if (rf->rf_flags & LAGG_F_HASHL2)
+ sc->sc_flags |= MBUF_HASHFLAG_L2;
+ if (rf->rf_flags & LAGG_F_HASHL3)
+ sc->sc_flags |= MBUF_HASHFLAG_L3;
+ if (rf->rf_flags & LAGG_F_HASHL4)
+ sc->sc_flags |= MBUF_HASHFLAG_L4;
LAGG_WUNLOCK(sc);
break;
case SIOCGLAGGPORT:
@@ -1806,120 +1815,6 @@
return (rval);
}
-static const void *
-lagg_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
-{
- if (m->m_pkthdr.len < (off + len)) {
- return (NULL);
- } else if (m->m_len < (off + len)) {
- m_copydata(m, off, len, buf);
- return (buf);
- }
- return (mtod(m, char *) + off);
-}
-
-uint32_t
-lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m, uint32_t key)
-{
- uint16_t etype;
- uint32_t p = key;
- int off;
- struct ether_header *eh;
- const struct ether_vlan_header *vlan;
-#ifdef INET
- const struct ip *ip;
- const uint32_t *ports;
- int iphlen;
-#endif
-#ifdef INET6
- const struct ip6_hdr *ip6;
- uint32_t flow;
-#endif
- union {
-#ifdef INET
- struct ip ip;
-#endif
-#ifdef INET6
- struct ip6_hdr ip6;
-#endif
- struct ether_vlan_header vlan;
- uint32_t port;
- } buf;
-
-
- off = sizeof(*eh);
- if (m->m_len < off)
- goto out;
- eh = mtod(m, struct ether_header *);
- etype = ntohs(eh->ether_type);
- if (sc->sc_flags & LAGG_F_HASHL2) {
- p = fnv_32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
- p = fnv_32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
- }
-
- /* Special handling for encapsulating VLAN frames */
- if ((m->m_flags & M_VLANTAG) && (sc->sc_flags & LAGG_F_HASHL2)) {
- p = fnv_32_buf(&m->m_pkthdr.ether_vtag,
- sizeof(m->m_pkthdr.ether_vtag), p);
- } else if (etype == ETHERTYPE_VLAN) {
- vlan = lagg_gethdr(m, off, sizeof(*vlan), &buf);
- if (vlan == NULL)
- goto out;
-
- if (sc->sc_flags & LAGG_F_HASHL2)
- p = fnv_32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
- etype = ntohs(vlan->evl_proto);
- off += sizeof(*vlan) - sizeof(*eh);
- }
-
- switch (etype) {
-#ifdef INET
- case ETHERTYPE_IP:
- ip = lagg_gethdr(m, off, sizeof(*ip), &buf);
- if (ip == NULL)
- goto out;
-
- if (sc->sc_flags & LAGG_F_HASHL3) {
- p = fnv_32_buf(&ip->ip_src, sizeof(struct in_addr), p);
- p = fnv_32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
- }
- if (!(sc->sc_flags & LAGG_F_HASHL4))
- break;
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- case IPPROTO_SCTP:
- iphlen = ip->ip_hl << 2;
- if (iphlen < sizeof(*ip))
- break;
- off += iphlen;
- ports = lagg_gethdr(m, off, sizeof(*ports), &buf);
- if (ports == NULL)
- break;
- p = fnv_32_buf(ports, sizeof(*ports), p);
- break;
- }
- break;
-#endif
-#ifdef INET6
- case ETHERTYPE_IPV6:
- if (!(sc->sc_flags & LAGG_F_HASHL3))
- break;
- ip6 = lagg_gethdr(m, off, sizeof(*ip6), &buf);
- if (ip6 == NULL)
- goto out;
-
- p = fnv_32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
- p = fnv_32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
- flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
- p = fnv_32_buf(&flow, sizeof(flow), p); /* IPv6 flow label */
- break;
-#endif
- }
-out:
- return (p);
-}
-
int
lagg_enqueue(struct ifnet *ifp, struct mbuf *m)
{
@@ -2087,15 +1982,12 @@
{
struct lagg_port *lp;
struct lagg_lb *lb;
- uint32_t seed;
lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO);
sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX;
- seed = arc4random();
- lb->lb_key = FNV1_32_INIT;
- lb->lb_key = fnv_32_buf(&seed, sizeof(seed), lb->lb_key);
+ lb->lb_key = m_ether_tcpip_hash_init();
sc->sc_psc = lb;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
@@ -2160,7 +2052,7 @@
M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
p = m->m_pkthdr.flowid >> sc->flowid_shift;
else
- p = lagg_hashmbuf(sc, m, lb->lb_key);
+ p = m_ether_tcpip_hash(sc->sc_flags, m, lb->lb_key);
p %= sc->sc_count;
lp = lb->lb_ports[p];
Index: sys/ofed/drivers/net/mlx4/en_tx.c
===================================================================
--- sys/ofed/drivers/net/mlx4/en_tx.c
+++ sys/ofed/drivers/net/mlx4/en_tx.c
@@ -49,7 +49,6 @@
#include <netinet/udp.h>
#include "mlx4_en.h"
-#include "utils.h"
enum {
MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
@@ -699,10 +698,10 @@
tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
}
-static unsigned long hashrandom;
+static uint32_t hashrandom;
static void hashrandom_init(void *arg)
{
- hashrandom = random();
+ hashrandom = m_ether_tcpip_hash_init();
}
SYSINIT(hashrandom_init, SI_SUB_KLD, SI_ORDER_SECOND, &hashrandom_init, NULL);
@@ -724,7 +723,7 @@
if (M_HASHTYPE_GET(mb) != M_HASHTYPE_NONE)
queue_index = mb->m_pkthdr.flowid;
else
- queue_index = mlx4_en_hashmbuf(MLX4_F_HASHL3 | MLX4_F_HASHL4, mb, hashrandom);
+ queue_index = m_ether_tcpip_hash(MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4, mb, hashrandom);
return ((queue_index % rings_p_up) + (up * rings_p_up));
}
Index: sys/ofed/drivers/net/mlx4/utils.h
===================================================================
--- sys/ofed/drivers/net/mlx4/utils.h
+++ sys/ofed/drivers/net/mlx4/utils.h
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014 Mellanox Technologies Ltd. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _MLX4_UTILS_H_
-#define _MLX4_UTILS_H_
-
-/* Lagg flags */
-#define MLX4_F_HASHL2 0x00000001 /* hash layer 2 */
-#define MLX4_F_HASHL3 0x00000002 /* hash layer 3 */
-#define MLX4_F_HASHL4 0x00000004 /* hash layer 4 */
-#define MLX4_F_HASHMASK 0x00000007
-
-uint32_t mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key);
-
-#endif /* _MLX4_UTILS_H_ */
Index: sys/ofed/drivers/net/mlx4/utils.c
===================================================================
--- sys/ofed/drivers/net/mlx4/utils.c
+++ sys/ofed/drivers/net/mlx4/utils.c
@@ -1,189 +0,0 @@
-/* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */
-
-/*
- * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/module.h>
-#include <sys/priv.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/hash.h>
-#include <sys/lock.h>
-#include <sys/rmlock.h>
-#include <sys/taskqueue.h>
-#include <sys/eventhandler.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_clone.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_llc.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/if_var.h>
-#include <net/bpf.h>
-
-#if defined(INET) || defined(INET6)
-#include <netinet/in.h>
-#endif
-#ifdef INET
-#include <netinet/in_systm.h>
-#include <netinet/if_ether.h>
-#include <netinet/ip.h>
-#endif
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/in6_ifattach.h>
-#endif
-
-#include <net/if_vlan_var.h>
-
-#include "utils.h"
-
-/* XXX this code should be factored out */
-/* XXX copied from if_lagg.c */
-
-static const void *
-mlx4_en_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
-{
- if (m->m_pkthdr.len < (off + len)) {
- return (NULL);
- } else if (m->m_len < (off + len)) {
- m_copydata(m, off, len, buf);
- return (buf);
- }
- return (mtod(m, char *) + off);
-}
-
-uint32_t
-mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key)
-{
- uint16_t etype;
- uint32_t p = key;
- int off;
- struct ether_header *eh;
- const struct ether_vlan_header *vlan;
-#ifdef INET
- const struct ip *ip;
- const uint32_t *ports;
- int iphlen;
-#endif
-#ifdef INET6
- const struct ip6_hdr *ip6;
- uint32_t flow;
-#endif
- union {
-#ifdef INET
- struct ip ip;
-#endif
-#ifdef INET6
- struct ip6_hdr ip6;
-#endif
- struct ether_vlan_header vlan;
- uint32_t port;
- } buf;
-
-
- off = sizeof(*eh);
- if (m->m_len < off)
- goto out;
- eh = mtod(m, struct ether_header *);
- etype = ntohs(eh->ether_type);
- if (flags & MLX4_F_HASHL2) {
- p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
- p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
- }
-
- /* Special handling for encapsulating VLAN frames */
- if ((m->m_flags & M_VLANTAG) && (flags & MLX4_F_HASHL2)) {
- p = hash32_buf(&m->m_pkthdr.ether_vtag,
- sizeof(m->m_pkthdr.ether_vtag), p);
- } else if (etype == ETHERTYPE_VLAN) {
- vlan = mlx4_en_gethdr(m, off, sizeof(*vlan), &buf);
- if (vlan == NULL)
- goto out;
-
- if (flags & MLX4_F_HASHL2)
- p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
- etype = ntohs(vlan->evl_proto);
- off += sizeof(*vlan) - sizeof(*eh);
- }
-
- switch (etype) {
-#ifdef INET
- case ETHERTYPE_IP:
- ip = mlx4_en_gethdr(m, off, sizeof(*ip), &buf);
- if (ip == NULL)
- goto out;
-
- if (flags & MLX4_F_HASHL3) {
- p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
- p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
- }
- if (!(flags & MLX4_F_HASHL4))
- break;
- switch (ip->ip_p) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- case IPPROTO_SCTP:
- iphlen = ip->ip_hl << 2;
- if (iphlen < sizeof(*ip))
- break;
- off += iphlen;
- ports = mlx4_en_gethdr(m, off, sizeof(*ports), &buf);
- if (ports == NULL)
- break;
- p = hash32_buf(ports, sizeof(*ports), p);
- break;
- }
- break;
-#endif
-#ifdef INET6
- case ETHERTYPE_IPV6:
- if (!(flags & MLX4_F_HASHL3))
- break;
- ip6 = mlx4_en_gethdr(m, off, sizeof(*ip6), &buf);
- if (ip6 == NULL)
- goto out;
-
- p = hash32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
- p = hash32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
- flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
- p = hash32_buf(&flow, sizeof(flow), p); /* IPv6 flow label */
- break;
-#endif
- }
-out:
- return (p);
-}
Index: sys/sys/mbuf.h
===================================================================
--- sys/sys/mbuf.h
+++ sys/sys/mbuf.h
@@ -1186,6 +1186,16 @@
((_m)->m_pkthdr.fibnum) = (_fib); \
} while (0)
+/* mbuf hash routines */
+
+#define MBUF_HASHFLAG_L2 (1 << 2)
+#define MBUF_HASHFLAG_L3 (1 << 3)
+#define MBUF_HASHFLAG_L4 (1 << 4)
+#define MBUF_HASHFLAG_MASK (MBUF_HASHFLAG_L2 | MBUF_HASHFLAG_L3 | MBUF_HASHFLAG_L4)
+
+uint32_t m_ether_tcpip_hash_init(void);
+uint32_t m_ether_tcpip_hash(const uint32_t, const struct mbuf *, const uint32_t);
+
#endif /* _KERNEL */
#ifdef MBUF_PROFILING

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 1, 11:21 AM (9 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14412393
Default Alt Text
D1987.vs4030.id4032.diff (48 KB)

Event Timeline