1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
|
%
% Copyright (c) 1999 University of Utah and the Flux Group.
% All rights reserved.
%
% The University of Utah grants you the right to copy and reproduce this
% document or portions thereof for academic, research, evaluation, and
% personal use only, provided that (1) the title page appears prominently,
% and (2) these copyright and permission notices are retained in all copies.
% To arrange for alternate terms, contact the University of Utah at
% csl-dist@cs.utah.edu or +1-801-585-3271.
%
\def\pd{packet dispatcher}
\def\netio{\texttt{netio}}
\label{pd}
\section{Introduction}
The \pd\ provides a mechanism for dispatching
packets to one of several entities using \emph{packet filter}
technology. The \pd\ API allows the
user to specify the type of packet filter machinery to be used
internally (BPF+, DPF, etc.).
The entities register their interest in a type of packet using
filter-specific packet descriptions.
The \pd\ later demultiplexes incoming packets to the correct owner or,
if a packet doesn't match any of the previously registered
descriptions, to a user-defined default \netio. (See
Section~\ref{oskit-netio} for general information about the \netio\
interface.)
The \pd's architecture is pictured in Figure~\ref{fig-pd-bw}.
There are two data paths: one for packet description
\emph{registration} and one for packet \emph{dispatch}. Packet
owners register interest in a certain type of packets
by calling {\tt oskit_packet_dispatcher_register} with
a description of the packets along with
a \netio\ object to which subsequently received,
matching packets are pushed. The \pd's PID (Process ID,
for lack of a better term) table
provides the level-of-indirection necessary to map
filter-generated Filter IDs with caller-supplied PIDs.
The type of packet filter used determines what format the packet
descriptions take on. (As of this writing, only a single packet filter
is implemented in the \oskit{}, but
the \pd\ code is implemented as if
more than one were available to ease the burden in future work.)
Because the \pd\ uses the \oskit{} \netio\ interface
for both incoming and outgoing channels, the definition
of a packet ``owner'' is not restricted in any way: it can run
on different threads or the same thread, it can dispatch
packets further or process them immediately, it can
process them inline or enqueue an event on an event queue.
Owners can be flows, threads, processes---whatever
model fits the context.
The \pd\ can be used in several different contexts:
used in conjunction with robust accounting,
it can detect a dearth in a packet owner's resources
before expending resources processing packets destined
to be dropped;
the \pd\ can be used to process non-traditional
packets such as IPv6; in an active network / server
environment, the \pd\ can be used to dispatch packets
to different Execution Environments.
\section{Example Use}
The example application {\tt examples/x86/more/pd_ex.c} creates a \pd\
which uses the \\
{\tt OSKIT_PD_FILTER_DPF_INTERP } filter type, creates and
registers a packet description for ARP requests, creates and registers
a packet description for ARP replies, and dispatches incoming packets
until a certain packet count is reached.
\section{Restrictions}
This section describes some of the important restrictions
the \pd\ places on its use and future work:
\begin{itemize}
\item{
Currently, the packet dispatcher uses the default \netio\
implementation which disallows writes to the packet {\tt bufio}
objects. If modification of a packet is desired, a copy
must be made first. A better implementation would
leverage the \oskit{} IOLite interface.
}
\item{
A {\tt oskit_packet_dispatcher_destroy}
call is needed.
}
\item{
Currently, only one \netio\ is associated with each
type of packet. Multiple owners of packets could be established
by subclassing from this simple \pd\ and
extending the PID table (which is implemented as a hash
table) to either to hold multiple \netio~s in its
[key,value] pairs.
}
\end{itemize}
\section{Sanity checking}
When the \oskit{} is compiled with debugging enabled ({\tt --enable-debug}),
a number of sanity checks are compiled to help detect bad parameters.
\section{API reference}
The following sections describe the functions exported by the Packet
Dispatcher in detail.
All of these functions, as well as the types necessary to use them,
are defined in the header file {\tt <oskit/pd.h>}.
%
% oskit_packet_dispatcher_create
%
\api{oskit_packet_dispatcher_create}{Create a packet dispatcher object}
\begin{apisyn}
\cinclude{oskit/pd.h}
\funcproto oskit_s32_t oskit_packet_dispatcher_create(
{\tt oskit_pd_t **}pd,
oskit_u32_t filter_type,
oskit_netio_t **push_netio,
oskit_netio_t *default_outgoing);
\end{apisyn}
\begin{apidesc}
Upon successful
return, {\tt pd} points to the newly created packet dispatcher.
In subsequent \pd\ operations, the caller must pass back
a pointer to the same {\tt pd} structure which acts as
a handle for the \pd.
The caller must provide a pointer to the default
\netio\ channel. Any packets which do not match any
registered packet description will be pushed to the default
\netio. For example, after creation but before any
{\tt oskit_packet_dispatcher_register} calls,
all received packets are routed to the default \netio\
since there are no
packet descriptions registered in the packet dispatcher.
The caller must provide a pointer to a \netio\
object. This pointer is initialized during the call to represent
the packet dispatcher's incoming channel.
\end{apidesc}
\begin{apiparm}
\item[pd]
Pointer to the \pd\ just created. Used as
a handle in subsequent \pd\ calls. The caller
should think of \pd\ as an opaque object;
modifications of the underlying structure are
not allowed.
\item[filter_type]
A constant representing what
filter machinery is desired for use inside
the \pd. The valid types are defined in
{\tt <oskit/pd.h>}. As of this writing, there
is only one valid type: {\tt OSKIT_PD_FILTER_DPF_INTERP }.
\item[push_netio]
\netio\ from which the \pd\ will receive packets.
One might later pass this argument
to {\tt oskit_etherdev_open}, for example.
\item[default_outgoing]
The \netio\ to which packets not matching any
specified filter are pushed by the dispatcher.
\end{apiparm}
\begin{apiret}
Returns 0 on success, or an error code specified in
{\tt <oskit/error.h>}, on error.
\end{apiret}
%
% oskit_packet_dispatcher_register
%
\api{oskit_packet_dispatcher_register}{Register an packet owner}
\begin{apisyn}
\cinclude{oskit/pd.h}
\funcproto oskit_s32_t oskit_packet_dispatcher_register(
{\tt oskit_pd_t **}pd,
oskit_s32_t *pdid,
oskit_netio_t *out_netio,
void *pdescr,
oskit_s32_t sz);
\end{apisyn}
\begin{apidesc}
This function is used to associate a packet owner (flow,
process, whatever) with a packet description. After
successful registration, the \pd\ will push packets
matching the given description to the given \netio. It
is the caller's responsibility to ensure their description
is unique so that ambiguity is avoided.
The format of the packet description is determined by
the {\tt filter_type} argument to the
{\tt oskit_packet_dispatcher_create} call.
\end{apidesc}
\begin{apiparm}
\item[pd]
Handle to the \pd returned from previous
call to {\tt oskit_packet_dispatcher_create}.
\item[pdid]
Upon return, the \pd\ ID associated with this packet
descriptor/owner pair. The user should use this
value to identify the pair when calling
{\tt oskit_packet_dispatcher_delete}. The value
is undefined if insertion wasn't successful (see
return value).
\item[out_netio]
Pointer to the \netio\ to which packets
matching {\tt pdescr} are pushed.
\item[pdescr]
A description of the packet. The format of
the packet description is dependent upon
the type of filter machinery specified in the
\pd\ creation call.
\item[sz]
The size of {\tt pdescr} in bytes.
\end{apiparm}
\begin{apiret}
Returns 0 on success, or an error code specified in
{\tt <oskit/error.h>}, on error.
\end{apiret}
%
% oskit_packet_dispatcher_delete
%
\api{oskit_packet_dispatcher_delete}{Disassociate a packet owner /
packet pair}
\begin{apisyn}
\cinclude{oskit/pd.h}
\funcproto oskit_s32_t oskit_packet_dispatcher_register(
{\tt oskit_pd_t **}pd,
oskit_s32_t fid);
\end{apisyn}
\begin{apidesc}
This function is used to disassociate a packet owner (flow,
process, whatever) from a packet description.
\end{apidesc}
\begin{apiparm}
\item[pd]
Handle to the \pd returned from previous
call to {\tt oskit_packet_dispatcher_create}.
\item[pdid]
The \pd\ ID of the owner/packet description pair
to be deleted. This ID was previously returned
in a call to {\tt oskit_packet_dispatcher_register}.
\end{apiparm}
\begin{apiret}
Returns 0 on success, or an error code specified in
{\tt <oskit/error.h>}, on error.
\end{apiret}
\psfigure{pd-bw}{
The Packet Dispatcher architecture has two data paths:
\emph{registration} and \emph{dispatch}. The PID table
provides the level-of-indirection necessary to map
filter-generated Filter IDs with caller-supplied PIDs.
}
|