dag_attach_stream(3)

NAME
dag_attach_stream - gain access to a receive or transmit stream on an Endace DAG card

SYNOPSIS
#include "dagapi.h "

int
dag_attach_stream(int dagfd, int stream_num, uint32_t flags, uint32_t extra_window_size);

DESCRIPTION
dag_attach_stream performs per-stream locking and memory mapping functions. The DAG descriptor dagfd is provided by dag_open(3). stream_num is an integer in the range [0, MAX_INTERFACES ] that indicates which stream to attach to. There are currently no flags defined.

To avoid seeing a packet record wrap over from the top of the circular buffer, a portion of the circular buffer is mapped into memory twice. This allows a record that would otherwise be split across the buffer boundary to appear contiguous. Traditionally the entire buffer is mapped twice. For example, a physical 32MB buffer space would be mapped into userspace twice, consuming 64MB of that process's virtual memory. This permits operation of the circular buffer with no restriction on how often buffer space must be cleared. When extra_window_size has the special value 0, this behavior is maintained. This can consume significant quantities of process virtual memory however when large physical buffers are used, such as 512MB. The extra_window_size parameter can be used to specify the size of the second buffer mapping. For example, with a 32MB physical buffer and extra_window_size set to 4MB, only 36MB of process virtual memory is used. When using dag_advance_stream(3), if extra_window_size is non-zero, the extra_window_size data is not processed before calling dag_advance_stream(3) again. This allows dag_advance_stream(3) to normalize the buffer pointers into the lower buffer mapping before the top of the second buffer mapping is reached. When using dag_rx_stream_next_record(3), extra_window_size must be at least as large as the maximum size packet possible on the link medium. For efficiency extra_window_size should be at least several megabytes, 4MB is a reasonable default.

When attaching a stream for transmission, extra_window_size must be set equal to or greater than the maximum sized block of data that is to be transmitted at once. For backwards compatibility (or if uncertain) set extra_window_size to zero.

RETURN VALUE
On success dag_attach_stream returns zero, otherwise it returns MAP_FAILED with errno set appropriately.

ERRORS

EACCES
    stream_num refers to a stream that is already locked by another process.

EBADF
    dagfd is an invalid file descriptor.

EINVAL
    stream_num is invalid or extra_window_size is too large.

EIO fatal internal error.

ENODEV
    the DAG card does not support packet capture.

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

Additional error codes as for ioctl(2), malloc(2), and mmap(2).

NOTES
dag_attach_stream obsoletes dag_mmap(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 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_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.