Show packet.asc syntax highlighted
EmStar Packet Device and Client
=============================
The EmStar Team <emstar-design@cens.ucla.edu>
$Id: packet.asc,v 1.4 2005/06/23 21:55:45 mlukac Exp $
Intro
-----
The packet device and client pair can be used for two or more
components to communicate data asynchronously.
A packet client writing data to a packet device is 'sending' a
packet. In the most basic form, the client's write will complete and
return before the packet device processes the data. What happens is
that the data the client writes get added to the end of an outgoing
queue for the specific client. Since there is only one thread of
execution, then as soon as there are no other pending events, the
packet device callback to process data from the outgoing queue is
called.
A packet client reading data from a packet device is a 'receive' by
the packet client. When the packet device has data to be delivered to
a client it adds to to the end of an incoming queue for a specific
client. This allows the client to asynchronously receive the data.
In addition to he basic functionality, the packet device supports
handling multiple clients and supports outgoing queue admission
control and client defined incoming queue filters.
<<X1,Packet Device Basic Usage>> +
<<X2,Packet Device Basic Usage - Code Examples>> +
<<X3,Packet Device Advanced Usage>> +
<<X4,Packet Device Advanced Usage - Code Examples>>
<<X5,Packet Client Basic Usage>> +
<<X6,Packet Client Basic Usage - Code Examples>> +
<<X7,Packet Client Advanced Usage>> +
<<X8,Packet Client Advanced Usage - Code Examples>>
Packet Device
-------------
Intro
~~~~~
As with all the other device libraries, the packet device is created
by first filling in a struct with pointers to the relevant callbacks,
then calling a constructor function.
For the packet device, the struct is
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#packet-dev-opts-t[packet_dev_opts_t].
As with the other device libraries, this struct contains a
link:http://lecs.cs.ucla.edu/api/emstar-glib-dev.html#g-device-opts-t[g_device_opts_t],
where at least the device name must be filled in using the
link:http://lecs.cs.ucla.edu/api/emstar-misc-sim.html#sim-path[sim_path()]
function. In addition to the device name, it is useful to provide a
pointer to a state struct using the device_info field in
g_device_opts_t. With each call back, you will have access to the
state pointer you set using the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-data[pd_data()]
function.
The packet_dev_opts_t struct should then be passed to the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#g-packet-dev[g_packet_dev()]
function along with a pd_context_t**. The pd_context_t** is typically
declared as a NULL pointer (a pd_context_t* pdc;) in main() or at the
top of the C file and passed to g_packet_dev() with a reference
(&pdc). The g_packet_dev() function will initialize and fill in the
pd_context_t.
The most basic usage of the packet device involves the send callback
and the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-receive[pd_receive()]
function call. Advanced usage includes using outgoing queue admission
control and client defined incoming queue filters.
Basic Usage[[X1]]
~~~~~~~~~~~~~~~~~
The basic usage for a packet device is using the send call back to
asynchronously process packets that are sent by clients and using the
pd_receive() function to deliver packets to be received by clients.
Send
^^^^
The send callback is triggered whenever there is packet in a
particular clients outgoing queue. A packet is added to a clients
outgoing queue when it has been completely written to the packet
device. The send call back will continue to fire as long as there are
packets in the outgoing queue. The queue is what enables the
asynchronous processing of packets by the packet devices: after the
packet is added to the outgoing queue, the client write completes. The
asynchronous processing allows a client to send a lot of packets
without being blocking and waiting for the packet device to process
each one.
The link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-send-cb-t[send callback]
you write has four parameters. The first is the pd_context_t
which you can use to retrieve the private data set in the
g_device_opts_t during initialization using the pd_data()
function. The second and third parameters provide the actual packet
data and the length of the packet written to the device. The third
parameter indicates whether the client that sent the packet had
previously requested that is receive its own packets as well. If the
loop_needed parameter is set to 1, then it is up to the send callbacks
writer to call
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-loop-receive[pd_loop_receive()]
after doing any transformations needed for loopback processing
(e.g. adding timestamps or addresses). The return value for the
callback is 0 if the packet was handled without error and it is all right for
for the send callback to be triggered again. For the other return
values, please see the API documentation page.
The size of the outgoing queue for all the clients can be specified in
the packet_dev_opts_t struct before initialization. The size of the
outgoing queue for any particular client can also be set (and
retrieved) by the packet client (see <<X7, Packet Client - Advanced Usage>> for more information).
Receive
^^^^^^^
The
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-receive[pd_receive()]
function is called by the packet device author whenever the packet
device has a packet to be delivered to a client (i.e. a received by the
client). pd_receive() places the packet into the clients incoming
queue and notifies the client that a packet is in the incoming
queue. The notify triggers an event on the client side to read from
the packet device; this is what make the pd_receive() call
asynchronous: pd_receive() and the calling function will complete
before the read is processed by the packet device. The read will
trigger a new event on the packet device that is handled internally by
the framework.
pd_receive() has three arguments: the pd_context_t for access to the
packet device state, a pointer to the data, and the length of the data
to be send. pd_receive() allocates new memory for the data, so it is
the callers responsibility to free any memory that was previous
allocated for the data. There is no return value.
The size of the incoming queue for all the clients can be specified in
the packet_dev_opts_t struct before initialization. The size of the
incoming queue for any particular client can also be set (and
retrieved) by the packet client (see <<X7, Packet Client- Advanced Usage>> for more information).
Basic Usage - Code Samples[[X2]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This code sample shows the two basic uses of a packet device: sending
and receiving packets.
To see the accompanying basic packet client code, please see the <<X6, Packet Client Basic Code Sample>> section.
Echo Server
^^^^^^^^^^^
The echo server is an EmStar component which echo's back packets sent
by clients. The code for the echo server is
link:http://www.lecs.cs.ucla.edu/lxr/source/emstar/libdev/examples/pd_echoserver.c[available here].
Starting with main(), there are a few things going on. Look at the
declaration of the packet_dev_opts_t struct: it is filled in with the
device name and a pointer to the send callback called pd_send() (which
is defined above). The packet_dev_opts_t struct is then passed as an
argument to g_packet_dev() which creates and initializes the packet
device.
Notice that we are also passing a pd_context_t to g_packet_dev(). This
pd_context_t is declared at the top of the file and is initialized by
g_packet_dev(). We have access to the pd_context_t in each of the
callbacks, so if we had set the device_info in the g_device_opts_t
contained in the packet_dev_opts_t we could access state (i.e. access
the device_info) initialized in main using the pd_data() function
call.
The rest of main() is straight forward. Two functions, misc_init()
and emrun_init(), are called in main(). For any component to have all
the features of EmStar enabled, it is critical to call these two
functions. Finally, g_main() is called, which puts the echo server
into the event loop, waiting for a read, write, or timer to fire.
Next look at the pd_send() callback. When triggered, all it does is
call pd_receive(). So, whenever a client writes a packet to the packet
device, it is put in the clients outgoing queue on the packet
device. After the clients write completes, the pd_send() callback is
triggered which calls pd_receive(). pd_receive() then puts the packet
into the clients incoming queue, triggering a read. Once send
callback completes, the clients read triggers and internal event and
the packet is read from the clients incoming queue.
So, running the pd_echoserver and the pd_client looks like the following.
In one terminal, run pd_echoserver:
--------------------------
[11:07:21][obj.i686-linux] libdev/examples/pd_echoserver
Mon Jun 20 11:07:36.877 2005: get_node_id: can't read node id from /etc/id: No such file or directory
Mon Jun 20 11:07:36.878 2005: main: Starting echoserver packet device at /dev/pd_echoserver!
Mon Jun 20 11:08:13.525 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:15.525 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:17.526 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:19.527 2005: pd_send: pd_send() called, echoing packet with pd_receive()
--------------------------
In the other terminal, run pd_client:
--------------------------
[11:08:10][obj.i686-linux] libdev/examples/pd_client -U /dev/pd_echoserver -s
<04,1119290891.520951>main: Opening packet device /dev/pd_echoserver
<04,1119290891.521714>main: Will send packets every 2 seconds
Mon Jun 20 11:08:11.522 2005: get_node_id: can't read node id from /etc/id: No such file or directory
Mon Jun 20 11:08:13.524 2005: send_packet: Sending packet
Mon Jun 20 11:08:13.525 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:15.525 2005: send_packet: Sending packet
Mon Jun 20 11:08:15.526 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:17.525 2005: send_packet: Sending packet
Mon Jun 20 11:08:17.527 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:19.526 2005: send_packet: Sending packet
Mon Jun 20 11:08:19.528 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:21.527 2005: send_packet: Sending packet
Mon Jun 20 11:08:21.528 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:23.528 2005: send_packet: Sending packet
--------------------------
Note: If you start up more than one pd_client while running the
pd_echoserver, you will notice that any packet one of the pd_client's
sends is received by all the other clients. This is because the
pd_receive() function delivers the packet to each clients incoming
queue.
To see the send functionality and the pd_receive() functionality in
separate components, please see the two following examples:
link:http://www.lecs.cs.ucla.edu/lxr/source/emstar/libdev/examples/pd_sendonly.c[pd_sendonly]:
implements the send callback and nothing else. It simply drops any
packets that are written to it. It can be run with the pd_client in
the same way the pd_echoserver was run, but the client will not
receive any of its packets back.
link:http://www.lecs.cs.ucla.edu/lxr/source/emstar/libdev/examples/pd_receiveonly.c[pd_receiveonly]:
only calls pd_receive(). It does this by creating a timer which fires
every two seconds. When the timer fires the call_receive function is
triggered, which calls pd_receive.
Real Code Examples
^^^^^^^^^^^^^^^^^^
(links to the lxr and a description here of what is going on)
Advanced Usage[[X3]]
~~~~~~~~~~~~~~~~~~~~
This advanced usage section covers using multiple clients, the open
and close callbacks, incoming and outgoing queue admission control,
debugging, and synchronous operation.
Multiple Clients
^^^^^^^^^^^^^^^^
A packet device can distinguish between multiple clients. There are a
set of functions and data structures to aid in handling multiple
clients. The multiple client facility allows you to deliver packets
only to certain clients and associate private state data with each
client. Each client also has its own incoming and outgoing queues.
Finding clients
+++++++++++++++
There are there functions for obtaining the current client, and
iterating through the entire internally maintained list of clients.
To being iterating through the internally maintained list of clients,
call the
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-client-top[pd_client_top()]
function. It will return the first pd_client_t in the internal
list. Subsequent calls should be made to
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-client-next[pd_client_next()],
which will return the next pd_client_t in the list or NULL if you have
reached the end of the list.
Typically this can be setup in a for loop as follows:
--------------------------
pd_client_t * pdc = pd_client_top(my_pd);
for ( ; pdc != NULL; pdc = pd_client_next(pdc) ) {
/* do stuff with pdc */
...
}
--------------------------
Additionally, you may only want to retrieve the current client being
serviced by a call back. To do this, use the
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-curr-client[pd_curr_client()]
function call. It will return the current client being processed if
there is one. If there is no current client the function returns NULL.
Some other useful functions in identifying clients are:
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-num-clients[pd_num_clients()],
which returns the number of clients, and
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-has-clients[pd_has_clients()],
which returns if there are any clients at all.
Setting and getting private data
++++++++++++++++++++++++++++++++
Once you have the pd_client_t for a particular client, you can set and
retrieve private data pointers for that particular client. This lets
you associate state with each client that opens the packet device for
reading, writing, or both.
To set the data for a particular pd_client_t, use the
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-set-client-data[pd_set_client_data()]
function. To later retrieve the data for a particular pd_client_t, use
the
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-client-data[pd_client_data()]
function.
Receive to specific clients
+++++++++++++++++++++++++++
One you have a pd_client_t and you want to have only that specific
client receive a packet, you can call
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-client-receive[pd_client_receive()]
to deliver data to that specific client. Alternatively, if you have
previous called pd_set_client_data(), you can call
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-receive-only[pd_receive_only()]
which searches through the clients and delivers the packet only to
clients which have the same private data pointer as the match_pointer argument.
Open and Close
^^^^^^^^^^^^^^
The open and close callbacks are useful in managing multiple
clients. They create the opportunity to initialize, set, and eventually
free any data you would want associated with each individual client
that is using the packet device. These callbacks are optional.
The
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-open-cb-t[open]
callback fires when a new client opens the packet device for reading
or writing. This presents an opportunity to use the pd_curr_client()
function to get pd_client_t struct for this particular client, and
initialize some private state and set it using the
pd_set_client_data() function. Later, during other callbacks or events
the data can be retrieved with the pd_client_data() function.
The
link:http://www.lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-open-cb-t[close]
callback fires when a client closes the packet device. This is
the appropriate time to free any private data associated with the
particular client by using the pd_curr_client() and pd_client_data()
functions to retrieve the data.
Enqueue
^^^^^^^
The link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-enqueue-cb-t[enqueue callback]
provides admission control to outgoing queues. It allows the packet
device to reject packets before the clients write completes and the
packet device send callback is triggered. It is an optional callback.
If the enqueue callback is set, it is triggered before the clients
write is allowed to complete. This means it is triggered before the
packet is added to the outgoing queue for the particular client. This
gives the packet device writer the chance to reject packets written by
the clients.
It is up to the packet device writer to determine the criteria that
causes packets to be rejected. It can be something about the data
being written, or even something about the current state of the
component containing the packet device. To reject a packet, the return
value of the enqueue call back must be less than 0. The return value
is actually returned to the client, so it is typical that the return
value is set according to the -errno scheme (see `man errno`).
Filter
^^^^^^
The packet device provides the ability for clients to set filters on
the incoming queues. The
linkhttp://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-filter-cb-t[filter callback]
is called before pd_receive() returns and before the packet is added
to a clients incoming queue. It is only called if the filter callback
has been set and the client has set a filter.
The filter can be almost anything. Typically is a bitmask that is
checked against an offset in the packet. The filter that the client
sets is a pd_filter_t with a length (maximum size is 128) and some
data. The same pd_filter_t is then passed to the filter callback and
it is up to the packet device writer to use the data in the
pd_filter_t to determine if the packet should be added to the queue or
not.
The filter callback should return 1 if the packet matches the filter
and should be added to the client incoming queue, and 0 otherwise.
4Since pd_receive() delivers packets to all the clients, the filter for
each client is potentially run when pd_receive() is called.
Unparse
^^^^^^^
The
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-unparse-cb-t[unparse callback]
provides the facility for the packet device writer to provide an
ASCII output for the packets being delivered to a client. It is an
optional callback.
If the unparse callback is defined, and the client has turned on ASCII
mode (turned off binary mode) for the packet device, then the unparse
is triggered and called on the data being taking out of the clients
incoming queue and being copied to the client.
Device Statistics
^^^^^^^^^^^^^^^^^
The packet device transparently maintains statistics about packets and
bytes transmitted and received and dropped using the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-stats-t[pd_stats_t]
struct. It does this both for the entire device, and for each
individual client.
To retrieve the statistics for the device, call the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-get-device-stats[pd_get_device_stats()]
function. To clear the stats for a device, call the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-clear-device-stats[pd_clear_device_stats()]
function.
Similarly to get the pd_stats_t for a particular client, you can use
the
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-get-client-stats[pd_get_client_status()]
function.
ioctl
^^^^^
The packet device has an optional
link:http://lecs.cs.ucla.edu/api/emstar-packet-dev.html#pd-ioctl-cb-t[ioctl callback].
If defined, this callback is triggered if an unrecognized ioctl has
been issued on the packet device. The packet device writer can use
this as an out of band communication channel with the packet client:
for instance there may be application specific parameters the client
would want to set or obtain.
Synchronous operation
^^^^^^^^^^^^^^^^^^^^^
Advanced Usage - Code Samples[[X4]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Packet Client
-------------
Intro
~~~~~
The packet client provides functions for working with packet devices
in two ways: the standard EmStar event/callback driven method as well
as directly operating on a packet device file descriptor.
The standard EmStar method provides a struct called
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-opts-t[pd_client_opts_t],
which can be filled in with callbacks and relevant settings for the
packet device, including the queue lengths and incoming filters. The
library expects at least the device name to be filled in using the
link:http://lecs.cs.ucla.edu/api/emstar-misc-sim.html#sim-path[sim_path()]
function. In addition to the device name, it is useful to provide a
pointer to a state struct (or two!) using the data pointer in the
pd_client_opts_t. With each callback, you will have access to the
state pointers you set using the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pdc-data[pdc_data()]
and pdc_data2() functions.
The pd_client_opts_t struct should then be passed to the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-open[pd_client_open()]
function along with a pd_client_context_t**. The pd_client_context_t**
is typically declared as a NULL pointer (a pd_client_context_t* pcc;)
in main() or at the top of the C file and passed to pd_client_open()
with a reference (&pcc). The pd_client_open() function will initialize
and fill in the pd_client_context_t.
Packet Client Basic Usage[[X5]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The basic usage of the packet client involves the receive callback and
the pd_client_send() function.
Send
^^^^
The
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-send[pd_client_send()]
function is used to send (write) data to the packet device. The
function takes three parameters: the pd_client_context_t which is used
to identify which packet device to write to, a pointer to the packet, and the length of the packet.
pd_client_send() will return the number of bytes sent, or a number
less than zero on error with errno set. If the outgoing queue is full,
errno will be set to EAGAIN.
The equivalent of pd_client_send() without using the packet client
framework is to just write() a packet to the packet device. If the
return value is less than 0, and the errno is set to EAGAIN, the the
output queue for the client is full. For other errors
Receive
^^^^^^^
The receive callback is triggered whenever a packet is completely read
from the client incoming queue on the packet device.
When the file descriptor for the packet device becomes readable, the
packet client library will try to read as many packets as it can from
the packet device. With each packet it reads, triggers the receive
callback (if it is defined).
The
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-receive-cb-t[receive]
callback has three arguments: a pointer to the packet, the length of
the packet, and a pd_client_context_t. The pd_client_context_t can be
used in combination with the pdc_data() and pdc_data2() function to
retrieve pointers to state data set during the packet client
initialization.
To continue the triggering of receive callbacks, the receive callback
must return EVENT_RENEW. Otherwise, return EVENT_DONE to destroy the
event and prevent the callback from ever firing again.
To temporarily disable to triggering of the receive callback without
destroying the event (you will not loose any packets until the queue
is full), use the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-readable-cb-set-enable[pd_client_readable_cb_set_enable()]
with the enable parameter set to 0. To re-enable the callback, call
the same function with the enable parameter set to 1. To determine
whether the callback is currently enabled or disabled, you can use the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-readable-cb-get-enable[pd_client_readable_cg_get_enable()]
function.
It is possible to call the standard read on the packet device file
descriptor.
Packet Client Basic Usage - Code Examples[[X6]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This code sample shows the two basic uses of a packet client: sending
and receiving packets.
To see the accompanying basic packet device code, please see the
<<X2, Packet Device Basic Code Sample>> section.
pd_client
^^^^^^^^^
The pd_client example code is an EmStar component which will send
packets using a packet device every two seconds, and print a notice
every time a packet is received.
Starting with main(), there are a few things going on. First, two
command line switches are checked for using the misc_opt library. The
first one (-U or --uses followed by a string) is used to tell the
client which packet device to open. The next switch is used to tell
the client whether it should send packets to the packet device or not.
After the command line parameters are called, the packet client is
initialized with the device name and the receive callback. Finally, if
the -s switch was part of the command line, a timer that fires every 2
seconds is started.
The rest of main() is straight forward. Two functions, misc_init() and
emrun_init(), are called in main(). For any component to have all the
features of EmStar enabled, it is critical to call these two
functions. Finally, g_main() is called, which puts the pd_client into
the event loop, waiting for the packet device fd to become readable,
or timer to fire.
Next, look at the send_packet() callback, which fires every two
seconds. Is simple creates a packet, and calls
pd_client_send(). Finally, look at the receive_packet function which
will fire whenever a packet is read from the packet device. It simply
prints that it has received a packet.
You can run the pd_client in combination with the pd_echoserver
(described in the packet device section above). The pd_client
component will send a packet every two seconds, and have it returned
by the echo server.
In one terminal, run pd_echoserver:
--------------------------
[11:07:21][obj.i686-linux] libdev/examples/pd_echoserver
Mon Jun 20 11:07:36.877 2005: get_node_id: can't read node id from /etc/id: No such file or directory
Mon Jun 20 11:07:36.878 2005: main: Starting echoserver packet device at /dev/pd_echoserver!
Mon Jun 20 11:08:13.525 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:15.525 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:17.526 2005: pd_send: pd_send() called, echoing packet with pd_receive()
Mon Jun 20 11:08:19.527 2005: pd_send: pd_send() called, echoing packet with pd_receive()
--------------------------
In the other terminal, run pd_client:
--------------------------
[11:08:10][obj.i686-linux] libdev/examples/pd_client -U /dev/pd_echoserver -s
<04,1119290891.520951>main: Opening packet device /dev/pd_echoserver
<04,1119290891.521714>main: Will send packets every 2 seconds
Mon Jun 20 11:08:11.522 2005: get_node_id: can't read node id from /etc/id: No such file or directory
Mon Jun 20 11:08:13.524 2005: send_packet: Sending packet
Mon Jun 20 11:08:13.525 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:15.525 2005: send_packet: Sending packet
Mon Jun 20 11:08:15.526 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:17.525 2005: send_packet: Sending packet
Mon Jun 20 11:08:17.527 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:19.526 2005: send_packet: Sending packet
Mon Jun 20 11:08:19.528 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:21.527 2005: send_packet: Sending packet
Mon Jun 20 11:08:21.528 2005: receive_packet: packet client got packet!, dropping
Mon Jun 20 11:08:23.528 2005: send_packet: Sending packet
--------------------------
Packet Client Advanced Usage[[X7]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Advanced usage of the packet client include setting the queue sizes,
setting a filter for the clients incoming queue on the packet device.
Setting Queue Options
^^^^^^^^^^^^^^^^^^^^^
The packet device has a few options specific to each client which can
be set by the packet client. These options are the incoming queue
length, the outgoing queue length, and whether loopback should be
enabled or not. The packet client library provides two ways of setting
queue options.
The first way is through the use the pd_client_opts_t structure during
initialization of the packet client. The q_opts member of the
pd_client_opts_t struct is a
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-queue-opts-t[pd_queue_opts_t]
struct, where you can set the the queue lengths and the loopback
mode. When the packet client is initialized, these values are
communicated to the packet device.
The second method is to directly call ioctl's on the file descriptor
for the packet device. The packet client library provides wrapper
functions for all the ioctl's to relieve the programmer from having to
remember all the right #defines. The
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html[packetclient]
API documentation contains a list of the #defines. There are two
wrapper functions for each queue and for the loopback mode. These
functions are all available with the following links:
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-set-loop-mode[pd_set_loop_mode()]
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-get-loop-mode[pd_get_loop_mode()]
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-set-incoming-qlen[pd_set_incoming_qlen()]
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-get-incoming-qlen[pd_get_incoming_qlen()]
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-set-outgoing-qlen[pd_set_outgoing_qlen()]
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-get-outgoing-qlen[pd_get_outgoing_qlen()]
Setting a Filter
^^^^^^^^^^^^^^^^
The packet device has the ability to filter packets before they are
placed in an packet clients incoming queue (the queue is on the packet
device side). How the filter is used is up to the packet device
writer.
The filter takes the form of a
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-filter-t[pd_filter_t],
which contains the length (the max being 128) and a data field. The
data can be used by the packet device in a variety of ways to
determine whether the packet should be rejected or not, but the
specific implementation depends on the purpose and the author of the
packet device.
The first way to set the filter is through the use of the
pd_client_opts_t struct during initialization of the packet
client. The pd_filter member of the pd_client_opts_t struct is a
pd_filter_t where you can set the filter and its length. When the
packet client is initialized, these values are communicated to the
packet device.
The second method is to directly call ioctl's on the file descriptor
for the packet device. The packet client library provides wrapper
functions for the ioctl's which get and set the filter to relieve the
programmer from having to remember all the right #defines. There are
two wrapper functions for the filter operations:
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-set-filter[pd_set_filter]
which will set the filter, and
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-get-filter[pd_get_filter]
which will get the current filter.
Configure Callback
^^^^^^^^^^^^^^^^^^
The
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-configure-cb-t[configure]
callback can be fires whenever the packet device is opened. One of the
parameters to the call back is the file descriptor of the newly
opened packet device. Using this file descriptor, you call any
extra/user defined ioctl's that were not covered by the options in the
pd_client_opts_t. This callback is called both when the packet device
is initially opened and every time it is reopened later in case of a
crash.
Writable Callback
^^^^^^^^^^^^^^^^^
The
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-writable-cb-t[writable]
callback fires when the file descriptor for the packet device becomes
writable. This function can be used to initiate sending packets if the
packet device temporarily became read only or went away.
To continue the triggering of writable callbacks, the writable callback
must return EVENT_RENEW. Otherwise, return EVENT_DONE to destroy the
event and prevent the callback from ever firing again.
To temporarily disable the triggering of the writable callback without
destroying the event, use the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-writable-cb-set-enable[pd_client_writable_cb_set_enable()]
function with the enable parameter set to 0. To re-enable the
callback, call the same function with the enable parameter set to
1. To determine whether the callback is currently enabled or disabled,
you can use the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-writable-cb-get-enable[pd_client_writable_cb_get_enable()]
function.
Setting ASCII Mode
^^^^^^^^^^^^^^^^^^
Turning on ASCII mode for a packet device causes the packet device to
trigger its unparse callback. The unparse callback translates the
binary packet into an ASCII format as the packet device writer
chooses, and then the packet is placed in the particular clients
incoming queue. This feature is useful for debugging.
The first was to set ASCII mode is through the use of the
pd_client_opts_t struct during initialization of the packet client. If
the ascii_mode member of the pd_client_opts_t is set to 1, it will
initialize the packet device in ascii mode for this client.
The second method for setting and unsetting the ASCII mode is to
directly call ioctl's on the file descriptor for the packet
device. The packets client library provides a wrapper function for the
ioctl's which get and set the filter to relieve the programmer from
having to remember all the right #defines. There is one wrapper
function called:
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-set-binary-mode[pd_set_binary_mode()]
which will set the packet device into ascii mode if the bin_mode
parameter is set to 0.
ioctl
^^^^^
If you are using the packet client library callbacks to access a
packet device, you do not have access to the file descriptor for the
packet device. To issue an ioctl without having access to the file
descriptor, you can use the
link:http://lecs.cs.ucla.edu/api/emstar-packet-client.html#pd-client-ioctl[pd_client_ioctl()]
function. This is useful if the packet device writer has implemented
extra functionality using the ioctl callback.
Sequential Reads
^^^^^^^^^^^^^^^^
Blocking Writes
^^^^^^^^^^^^^^^
Packet Client Advanced Usage - Code Examples[[X8]]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Real Code Examples
^^^^^^^^^^^^^^^^^^
(links to the lxr and a description here of what is going on)
See more files for this project here