Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / host / lib / eth_buffer.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 #ifndef INCLUDED_USRP2_ETH_BUFFER_H
22 #define INCLUDED_USRP2_ETH_BUFFER_H
23
24 #include "pktfilter.h"
25 #include <eth_common.h>
26 #include <boost/utility.hpp>
27 #include <vector>
28 #include <memory>
29 #include <stdint.h>
30
31 namespace usrp2 {
32
33   class ethernet;
34   class data_handler;
35
36   /*!
37    * \brief high-performance interface to send and receive raw
38    * ethernet frames with out-of-order retirement of received frames.
39    *
40    * On many systems it should be possible to implement this on top of libpcap
41    *
42    * \internal
43    */
44   class eth_buffer : boost::noncopyable 
45   {
46     
47     int           d_fd;                 // socket file descriptor
48     uint8_t       d_mac[6];             // our mac address
49     bool          d_using_tpring;       // using kernel mapped packet ring
50     size_t        d_buflen;             // length of our buffer
51     uint8_t      *d_buf;                // packet ring
52     unsigned int  d_frame_nr;           // max frames on ring
53     size_t        d_frame_size;         // frame storage size
54     unsigned int  d_head;               // pointer to next frame
55
56     std::vector<uint8_t *>  d_ring;     // pointers into buffer
57     std::auto_ptr<ethernet> d_ethernet; // our underlying interface
58   
59     bool frame_available();
60
61     void inc_head()
62     {
63       if (d_head + 1 >= d_frame_nr)
64         d_head = 0;
65       else
66         d_head = d_head + 1;
67     }
68
69
70   public:
71
72     enum result {
73       EB_OK,            //< everything's fine
74       EB_ERROR,         //< A non-recoverable error occurred
75       EB_WOULD_BLOCK,   //< A timeout of 0 was specified and nothing was ready
76       EB_TIMED_OUT,     //< The timeout expired before anything was ready
77     };
78
79     static const unsigned int MAX_PKTLEN = 1512;
80     static const unsigned int MIN_PKTLEN = 64;
81
82     /*!
83      * \param rx_bufsize is a hint as to the number of bytes of memory
84      * to allocate for received ethernet frames (0 -> reasonable default)
85      */
86     eth_buffer(size_t rx_bufsize = 0);
87     ~eth_buffer();
88     
89     /*!
90      * \brief open the specified interface
91      *
92      * \param ifname ethernet interface name, e.g., "eth0"
93      * \param protocol is the ethertype protocol number in network order.
94      *    Use 0 to receive all protocols.
95      */
96     bool open(const std::string &ifname, int protocol);
97
98     /*!
99      * \brief close the interface
100      */
101     bool close();
102
103     /*!
104      * \brief attach packet filter to socket to restrict which packets read sees.
105      * \param pf        the packet filter
106      */
107     bool attach_pktfilter(pktfilter *pf);
108
109     /*!
110      * \brief return 6 byte string containing our MAC address
111      */
112     const uint8_t *mac() const { return d_mac; }
113
114     /*!
115      * \brief Call \p f for each frame in the receive buffer.
116      * \param f is the frame data handler
117      * \param timeout (in ms) controls behavior when there are no frames to read
118      *
119      * If \p timeout is 0, rx_frames will not wait for frames if none are 
120      * available, and f will not be invoked.  If \p timeout is -1 (the 
121      * default), rx_frames will block indefinitely until frames are 
122      * available.  If \p timeout is positive, it indicates the number of
123      * milliseconds to wait for a frame to become available.  Once the
124      * timeout has expired, rx_frames will return, f never having been 
125      * invoked.
126      *
127      * \p f will be called on each ethernet frame that is available.
128      * \p f returns a bit mask with one of the following set or cleared:
129      * 
130      * data_handler::KEEP  - hold onto the frame and present it again during 
131      *                       the next call to rx_frames, otherwise discard it
132      *
133      * data_handler::DONE -  return from rx_frames now even though more frames
134      *                       might be available; otherwise continue if more 
135      *                       frames are ready.
136      *
137      * The idea of holding onto a frame for the next iteration allows
138      * the caller to scan the received packet stream for particular
139      * classes of frames (such as command replies) leaving the rest
140      * intact.  On the next call all kept frames, followed by any new
141      * frames received, will be presented in order to \p f.  
142      * See usrp2.cc for an example of the pattern.
143      *
144      * \returns EB_OK if at least one frame was received
145      * \returns EB_WOULD_BLOCK if \p timeout is 0 and the call would have blocked
146      * \returns EB_TIMED_OUT if timeout occurred
147      * \returns EB_ERROR if there was an unrecoverable error.
148      */
149     result rx_frames(data_handler *f, int timeout=-1);
150
151     /*
152      * \brief Release frame from buffer
153      *
154      * Call to release a frame previously held by a data_handler::KEEP.
155      * The pointer may be offset from the base of the frame up to its length.
156      */
157     void release_frame(void *p);
158
159     /*
160      * \brief Write an ethernet frame to the interface.
161      *
162      * \param base points to the beginning of the frame (the 14-byte ethernet header).
163      * \param len is the length of the frame in bytes.
164      * \param flags is 0 or the bitwise-or of values from eth_flags
165      *
166      * The frame must begin with a 14-byte ethernet header.
167      *
168      * \returns EB_OK if the frame was successfully enqueued.
169      * \returns EB_WOULD_BLOCK if flags contains EF_DONT_WAIT and the call would have blocked.
170      * \returns EB_ERROR if there was an unrecoverable error.
171      */
172     result tx_frame(const void *base, size_t len, int flags=0);
173
174     /*
175      * \brief Write an ethernet frame to the interface using scatter/gather.
176      *
177      * \param iov points to an array of iovec structs
178      * \param iovcnt is the number of entries
179      * \param flags is 0 or the bitwise-or of values from eth_flags
180      *
181      * The frame must begin with a 14-byte ethernet header.
182      *
183      * \returns EB_OK if the frame was successfully enqueued.
184      * \returns EB_WOULD_BLOCK if flags contains EF_DONT_WAIT and the call would have blocked.
185      * \returns EB_ERROR if there was an unrecoverable error.
186      */
187     result tx_framev(const eth_iovec *iov, int iovcnt, int flags=0);
188
189     /*
190      * \brief Returns maximum possible number of frames in buffer
191      */
192     unsigned int max_frames() const { return d_frame_nr; }
193
194   };
195
196 };  // namespace usrp2
197
198 #endif /* INCLUDED_USRP2_ETH_BUFFER_H */