
              SIMPLIFIED ASYNCHRONOUS NETWORK PROCESSOR API


*****************
* FRAME BUFFERS *
*****************



Structure
---------

struct fbuffer
{
  int len;
  int ifnum;
  int ofnum;
  char frame[1];
};

A frame buffer (struct fbuffer) is a structure which stores a frame and 
information about it. 



Fields
------

The "len" field is set to the total length of the frame.

The "ifnum" field is set to the number of the interface on which the frame was
received.  Valid values depend on the network processor.  Valid values on the
IXP1200 Bridal Veil boards are 0-3.

The "ofnum" field is set to the number of the interface on which the frame will
be sent (by send_frame()).  Valid values depend on the network processor.  
Valid values on the IXP1200 Bridal Veil boards are 0-3.

The "frame" field is a handle to the memory containing the actual frame data
including any frame headers.



Allocation
----------

A programmer should never declare a frame buffer variable directly.  He should 
instead allocate memory sufficient for holding a frame plus the control 
information held in a frame buffer, and store the address of this memory in a
frame buffer pointer.  The new_fbuf() function (see below) can be used to 
allocate a frame buffer from heap space (using malloc) specifying only the 
length of frame field.

Dynamically allocated frame buffers must be disposed of by the programmer.  
None of this API's functions attempt to deallocate the memory pointed to by a 
frame buffer pointer.

Examples: 
(assume we are working in an Ethernet only environment so frames have a maximum
size of 1500 bytes plus the Ethernet header)

  struct fbuffer *fb;
  int buffer[2048];

  fb = (struct fbuffer *)buffer;
  fb = malloc(1514 + sizeof(int) * 3);
  fb = new_fbuf(1514);



*************
* FUNCTIONS *
*************

Function List:
--------------
np_start()
np_stop()
recv_frame()
next_frame()
send_frame()
iface_ready()
new_fbuf()
set_promisc()
get_mac()


Name:			-- The name of the function
Prototype:		-- The function's formal prototype
Arguments:		-- The parameters of the function
Summary:		-- A quick description of what the function does
Returns Value		-- What the function returns
Side Effects:		-- Values modified in global state or parameters
Description:		-- In depth description of the function





Name:
-----
np_start


Prototype:
----------
int np_start(char *npaddr, char *ifacename);


Arguments:
----------
npaddr		-- The address of the network processor
ifacename	-- The block name of the interface ACE on the network processor


Summary:
--------
Opens a session to the network processor.


Return Value:
-------------
Returns 0 on success and -1 on an error.


Side Effects:
-------------
Modifies global state with session information.
Sets all interfaces into promiscuous mode.


Description:
------------
The np_start() function initializes a session with a network processor. 
The functions recv_frame(), next_frame(), send_frame, and iface_ready() will 
not operate correctly if a session has not first been initialized using 
np_start().  The "npaddr" argument gives the IP address at which to connect to 
the network processor.  If this argument is set to NULL, then a default of 
"127.0.0.1" will be used.  This will work fine if the program calling 
np_start() is running on the network processor itself.  The ifacename gives the 
block name of the Interface ACE running on the network processor.  This is 
specified in the ixsys.config configuration file on the network processor and 
is usually set to "ifaceInput".  Passing a NULL in this argument will try that 
default.  np_start() returns 0 on successful session establishment and -1 on 
an error.

A session started with np_start() should be closed by the np_stop() function.
Furthermore, the np_start() function modifies (hidden) global state.  Only one
session can be established at a time.

The np_start() function also has the side-effect of setting all the interfaces
on the network processor into promiscuous mode.  This can be reversed using
set_promsic().  The np_stop() function also puts all interfaces back into
non-promiscuous mode.



Name:
-----
np_stop


Prototype:
----------
void np_stop();


Arguments:
----------
None.


Summary:
--------
Ends a session with a network processor established by np_start().
Turns off promiscuous mode on all interfaces on the network processor.


Return Value:
-------------
Returns 0 on success and -1 on failure.


Side Effects:
-------------
Modifies global state by erasing session information.


Description:
------------
The np_stop() function terminates a session with a network processor.  The
session must have been established with the successful invocation of the
np_start() function.  Only after np_stop() has been called can a new session be
established using np_start().  After calling np_stop() (but before another
np_start() is called) the functions recv_frame(), next_frame(), send_frame(),
and iface_ready() will not operate properly.  The np_stop() function also turns 
off promiscuous mode on all the interfaces in the network processor.   The
set_promisc() function can be used to set them back into promiscuous mode as
necessary.



Name:
-----
recv_frame


Prototype:
----------
void recv_frame(int ifnum, struct fbuffer *fbuf);


Arguments:
----------
ifnum		-- The interface to receive a frame from.
fbuf		-- The frame buffer to store the frame in.


Summary:
--------
Waits until a frame arrives on interface "ifnum" and then copies it into
"fbuf".


Return Value:
-------------
None.


Side Effects:
-------------
Stores a frame in the location referred to by the "fbuf" argument.


Description:
------------
The recv_frame() function blocks until a frame arrives on interface "ifnum".
The function will continue to block even if frames arrive on interfaces other
than the one specified in "ifnum".  If frames have already arrived on that 
interface they will be enqueued (up to a set maximum) by the network processor 
until they are dequeued by recv_frame() or next_frame().  If frames have been 
enqueued at the network processor then recv_frame() returns immediately.  The 
iface_ready() function (see below) can be used to test whether frames have been 
enqueued at the network processor.

The "fbuf" argument must point to an allocated frame buffer large enough to
hold the maximum sized frame that can arrive.  If a frame arrives larger than
a frame buffer can hold, a buffer overflow will result.  The "ifnum" field in
frame buffer will be set to the "ifnum" parameter.



Name:
-----
next_frame


Prototype:
----------
void next_frame(struct fbuffer *fbuf);


Arguments:
----------
fbuf		-- A pointer to a frame buffer to store the frame in.


Summary:
--------
Waits for the next frame on any interface and copies it into a frame buffer.


Return Value:
-------------
None.


Side Effects:
-------------
Stores a frame in the location referred to by the "fbuf" argument.


Description:
------------
The next_frame() function blocks until a frame arrives on any interface.
If frames have already arrived on an interface they will be enqueued (up to a 
set maximum) by the network processor until they are dequeued by recv_frame() 
or next_frame().  If frames have been enqueued at the network processor then 
next_frame() returns immediately.  The iface_ready() function (see below) can 
be used to test whether frames have been enqueued at the network processor.

The "fbuf" argument must point to an allocated frame buffer large enough to
hold the maximum sized frame that can arrive.  If a frame arrives larger than
a frame buffer can hold, a buffer overflow will result.  The "ifnum" field in
frame buffer will be set to the interface on which the frame arrived.




Name:
-----
send_frame


Prototype:
----------
void send_frame(struct fbuffer *fbuf, int safill);


Arguments:
----------
fbuf		-- A frame buffer containing a frame to send.
safill		-- Tells whether or not to fill in the source MAC address in
		   outgoing frame.


Summary:
--------
Queues a frame for sending on the network processor.


Return Value:
-------------
None.


Side Effects:
-------------
None.


Description:
------------
The send_frame() function queues a frame for transmission on the network
processor.  Since multiple queues are used internally in the network processor
and any of them could conceivably overflow, calling send_frame() does not
guarantee that the frame will actually be sent.  (though in practice loss of
frames queued for transmission should be very rare)  The "ofnum" field of the
frame buffer "fbuf" passed as an argument to send_frame() determines which
interface the frame will be sent out on.  There is no mechanism to
automatically broadcast a frame on all interfaces.  (i.e. the user must call
send_frame() on each interface to simulate a broadcast)  

If the "safill" argument is set to a non-zero then the source MAC address of
the frame will be filled in with the MAC address of the interface the frame is
sent out on.  Otherwise the frame is sent out exactly as it is passed to
frame_send().




Name:
-----
iface_ready


Prototype:
----------
int iface_ready(int ifnum, int direction);


Arguments:
----------
ifnum		-- The interface to check for queued packets.
direction	-- One of INGRESS or EGRESS (defined in npapi.h)


Summary:
--------
Checks whether a call to read frames from an interface (i.e. recv_frame) or
write frames to an interface (i.e. send_frame()) will block.


Return Value:
-------------
Return 1 if the call will block, and 0 if the call will not block.


Side Effects:
-------------
None.


Description:
------------
The iface_ready() function is used to test whether an interface is ready to
receive packets from or send packets to.  The "iface" argument gives the
interface to test, while the "direction" argument tells whether to test if the
interface is ready for an ingress or egress operation (reading a packet or
writing a packet).



Name:
-----
new_fbuf


Prototype:
----------
struct fbuffer *new_fbuf(int flen);


Arguments:
----------
flen		-- The amount of space (in bytes) to allocate for the "frame"
		   field of the fbuffer.


Summary:
--------
Allocates a new frame buffer of specified size.


Return Value:
-------------
Returns a pointer to a new frame buffer.  If there is no memory left for a new
frame buffer in the heap it returns NULL.


Side Effects:
-------------
None.


Description:
------------
The new_fbuf() function allocates a new frame buffer from dynamic (heap)
memory.  The new frame buffer will have a "frame" field that can store up to 
"flen" bytes of frame data.  (Remember to count headers when computing the
amount of space to request for the "frame" field.)  The new frame buffer can be
deallocated with the free() function.  The "len" field of the new frame buffer
is initialized to "flen".  The "ifnum" field of the frame buffer is initialized
to 0.  This is because even frames fabricated on the network processor must
have a valid input interface in order to be transmitted properly.  new_fbuf()
returns a pointer to the new frame buffer on success or a NULL if the heap
store has been exhausted.




Name:
-----
set_promisc


Prototype:
----------
int set_promisc(char *iname, int iface, int on);


Arguments:
----------
iname		-- The block name of the interface ACE of the network processor.
iface		-- The interface to manipulate.
on		-- Whether to turn promiscuous mode on (non-zero) or off (zero).


Summary:
--------
Turns promiscuous mode on or off for a specified interface.


Return Value:
-------------
Returns a 0 on a success and a negative value on a failure.


Side Effects:
-------------
Modifies the promiscuous mode of an interface on the network processor.


Description:
------------
The set_promisc() function is used to put an interface on a network processor 
into promiscuous mode or take it out of promiscuous mode depending on the "on"
parameter.  If a non-zero is passed in "on" the interface will be placed in
promiscuous mode and if a 0 is passed in "on" the interface will be taken out
of promiscuous mode.  The "iname" parameter specifies the block name of the
interface ACE of the network processor.  This is usually "ifaceInput", but is
specified in the ixsys.config file on the network processor.  The "iface"
parameter determines which interface will be manipulated.  The set_promisc() 
function returns a 0 on a success and a negative value on a failure.

It is worth noting that np_start() calls set_promisc() to put every interface
in promiscuous mode when a session is established.  Likewise, np_stop() calls
set_promisc() for each interface to take it out of promiscuous mode.

CHANGEME?  Must it be run on the NP itself?



Name:
-----
get_mac


Prototype:
----------
int get_mac(char *iname, int iface, unsigned char addr[6]);


Arguments:
----------
iname		-- The block name of the interface ACE
iface		-- The interface to get the MAC address of
addr		-- Where to store the MAC address


Summary:
--------
Gets the MAC address of a specified interface.


Return Value:
-------------
Returns 0 on a success and a negative value if an error occurred.


Side Effects:
-------------
None.


Description:
------------
The get_mac() function queries the interface ACE on a network processor for the
MAC address of a specified interface.  "iname" must give the block name of the
interface ACE on the network processor.  This is usually "ifaceInput" but is
set in the file ixsys.config.  The "iface" parameter gives the interface for
which to find the MAC address.  The "addr" argument specifies the location in
which to store the result.  At present only 48-bit Ethernet MAC addresses are
supported by this function.  The get_mac() function returns a 0 on success and
a negative value on failure.

It is worth noting that the np_start() function calls get_mac() for each 
interface to determine what to fill in as the source address of a frame should
the "safill" option be used in send_frame().
