dag_rx_stream_next_record(3)

NAME
dag_rx_stream_next_record - receive a single ERF record from an Endace DAG card

SYNOPSIS
#include "dagapi.h "

uint8_t*
dag_rx_stream_next_record(int dagfd, int stream_num);

DESCRIPTION
dag_rx_stream_next_record is used for receiving ERF records individually, rather than the block oriented approach of dag_advance_stream(3).

This is a simpler approach and may ease porting from other packet-oriented approaches (e.g. libpcap), but due to the function call per packet the overhead may be 10% higher. dag_advance_streamanddag_rx_stream_next_record should not be mixed on a single stream while the stream is started. The function 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(3) the default stream parameters will cause dag_rx_stream_next_record(3) to block when no data is available.

RETURN VALUE
On success dag_rx_stream_next_record returns a pointer to a single ERF record, otherwise it returns NULL with errno set appropriately.

ERRORS

EAGAIN
    timeouts are enabled and no data was available.

EBADF
    dagfd is an invalid file descriptor.

EINVAL
    stream_num refers to a stream that has not been attached or size is larger than the size of the stream's memory buffer.

EIO the next ERF record has an invalid ERF type. This is usually a fatal error requiring the capture session to be restarted.

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

ENOTTY
    stream_num does not refer to a receive stream.

Additional error codes as for dag_advance_stream(3).

NOTES
The ERF header contains an record length field that specifies the size of the record, so the record length is not returned with the routine call.

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 keep_processing() routine returns 0 (the code for this routine is not shown, but typically it would check a timer or a variable set by a signal handler or thread to determine when the capture session should end).

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 mindata = 32*1024;
    struct timeval poll;
    struct timeval maxwait;
    int dagfd;
    int result;
    /* 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, stream, mindata, &maxwait, &poll);
    /* Main packet processing loop. */
    while (keep_processing())
    {
    	dag_record_t* record = (dag_record_t*) dag_rx_stream_next_record(dagfd, stream);
    	if (NULL != record)
    	{
    		int length = ntohs(record->rlen);

    		process_packet(record, length); /* Packet processing routine. */
    	}
    	else
    	{
    		if (errno != EAGAIN)
    		{
    			fprintf(stderr, "dag_rx_stream_next_record(%s): %s", dagname, strerror(errno));
    			exit(EXIT_FAILURE);
    		}
    	}
    }
    /* Finished; stop capture, detach from stream and close. */
    dag_stop_stream(dagfd, stream);
    dag_detach_stream(dagfd, stream);
    dag_close(dagfd);

SEE ALSO
dag_advance_stream(3), 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_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.