dag_advance_stream(3)

NAME
dag_advance_stream - receive a block of ERF records from an Endace DAG card

SYNOPSIS
#include "dagapi.h "

uint8_t*
dag_advance_stream(int dagfd, int stream_num, uint8_t** bottom);

DESCRIPTION
dag_advance_stream operates by returning a pair of pointers into the stream buffer, which is mapped into the user process space in the dag_advance_stream call. bottom is a pointer to a void pointer, which should be NULL on the first call.

On subsequent calls, this should contain the address up to which the user has completed processing. dag_advance_stream can change the value of bottom to renormalize the circular buffer, so it is a pointer to a pointer. The return value is a pointer to the top of the available buffer space. For example:
	void* bottom = NULL;
	void* top = NULL;
	top = dag_advance_stream(dagfd, 0, &bottom);

Assuming the buffer is mapped into user space at 10000, bottom will now contain 10000, and if 10000 bytes were received top would contain 20000. Processing can now begin for ERF records, starting at bottom (10000) and continue until you reach top (20000). If the first 5000 bytes are processed and it is then decided to call dag_advance_stream again, the call would be:
	bottom = bottom + 5000;
	top = dag_advance_stream(dagfd, 0, &bottom);

After this call bottom may still contain 15000, but top may be 25000 if a further 5000 bytes were received while process the initial 5000 bytes are being processed. If the circular buffer needs to be normalized, then bottom can have a lower value after calling dag_advance_stream than what was passed in. The process is always started from bottom. After calling dag_advance_stream the top pointer will always have a higher value than the bottom pointer.

RETURN VALUE
On success dag_advance_stream returns a pointer to the top of the available buffer space, otherwise it returns NULL with errno set appropriately.

ERRORS

EBADF
    dagfd is an invalid file descriptor.

EINVAL
    stream_num refers to a stream that has not been attached.

EIO internal error. This is usually a fatal internal error requiring the capture session to be restarted.

ENOMEM
    stream_num refers to a stream that has no memory allocated to its buffer.

NOTES
Since dag_advance_stream can return more than one ERF record at a time, it will usually be more efficient than using dag_rx_next_record(3).

dag_advance_stream uses the stream poll parameters described under dag_get_stream_poll(3). These parameters define the blocking or nonblocking behavior, as well as the optional timeout and poll period. If not configured with dag_set_stream_poll the default stream parameters will cause dag_advance_stream to block when no data is available.

dag_advance_stream obsoletes dag_offset(3).

EXAMPLE
The following sample program opens the DAG card corresponding to /dev/dag0, configures it for variable length record capture with a snap length of 1536 bytes and captures ERF records on stream 0 (the first receive stream). The capture continues until the global variable gRun is set to a value other than 1 (the code to do this is not shown, but would typically be done from a signal handler or another thread).

Error-handling is rudimentary; rather than attempt to undo the partial work done when opening and configuring the card, this code prints an error message describing the call that failed and exits.

    const char* dagname = "/dev/dag0";
    const char* config = "slen=1536 varlen";
    int stream = 0;
    int flags = 0;
    int extra_window_size = 4*1024*1024;
    int dagfd;
    int result;
    struct timeval poll;
    struct timeval maxwait;
    uint8_t* bottom = NULL;
    uint8_t* top = NULL;
    /* Open DAG, configure, and attach to receive stream 0. */
    dagfd = dag_open(dagname);
    if (-1 == dagfd)
    {
    	fprintf(stderr, "dag_open(%s): %s, dagname, strerror(errno));
    	exit(EXIT_FAILURE);
    }
    result = dag_configure(dagfd, config);
    if (-1 == result)
    {
    	fprintf(stderr, "dag_configure(%s, %s): %s, dagname, config, strerror(errno));
    	exit(EXIT_FAILURE);
    }
    result = dag_attach_stream(dagfd, stream, flags, extra_window_size);
    if (-1 == result)
    {
    	fprintf(stderr, "dag_attach_stream(%s): %s, dagname, strerror(errno));
    	exit(EXIT_FAILURE);
    }
    result = dag_start_stream(dagfd, stream);
    if (-1 == result)
    {
    	fprintf(stderr, "dag_start_stream(%s): %s, dagname, strerror(errno));
    	exit(EXIT_FAILURE);
    }
    /* Initialise DAG polling parameters. */
    timerclear(&maxwait);
    maxwait.tv_usec = 100 * 1000; /* 100ms timeout. */
    timerclear(&poll);
    poll.tv_usec = 10 * 1000;     /* 10ms poll interval. */
    /* 32kB minimum data to return. */
    dag_set_stream_poll(dagfd, 0, 32*1024, &maxwait, &poll);
    /* Main packet processing loop. */
    while (keep_processing())
    {
    	uint32_t diff;
    	top = dag_advance_stream(dagfd, stream, &bottom);
    	diff = top - bottom;
    	if (diff == 0)
    	{
    		continue;
    	}
    	while (keep_processing() && ((top - bottom) > dag_record_size))
    	{
    		const char* rec = (const char*) bottom;
    		int length = get_record_length(rec);
    		if ((top - bottom) < length)
    		{
    			break;
    		}

    		process_packet(rec, length);
    		bottom += length;
    	}
    }
    /* Finished; stop capture, detach from stream and close. */
    dag_stop_stream(dagfd, stream);
    dag_detach_stream(dagfd, stream);
    dag_close(dagfd);

SEE ALSO
dag_attach_stream(3), dag_detach_stream(3), dag_get_stream_buffer_level(3), dag_get_stream_buffer_size(3), dag_get_stream_poll(3), dag_rx_get_stream_count(3), dag_rx_stream_next_inline(3), dag_rx_stream_next_record(3), dag_set_stream_poll(3), dag_start_stream(3), dag_stop_stream(3).

BUGS
Report bugs to <support@endace.com>.

LAST UPDATED
$Author: koryn $
$Revision: 2481 $
$Date: 2005-11-10 14:52:13 +1300 (Thu, 10 Nov 2005) $

COPYRIGHT
(c) 2004-2005 Endace Technology, Hamilton, New Zealand. All Rights Reserved.