GNU Radio 3.3.0 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2008 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License along 00018 * with this program; if not, write to the Free Software Foundation, Inc., 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 */ 00021 #ifndef INCLUDED_USRP2_ETH_BUFFER_H 00022 #define INCLUDED_USRP2_ETH_BUFFER_H 00023 00024 #include "pktfilter.h" 00025 #include <eth_common.h> 00026 #include <boost/utility.hpp> 00027 #include <vector> 00028 #include <memory> 00029 #include <stdint.h> 00030 00031 namespace usrp2 { 00032 00033 class ethernet; 00034 class data_handler; 00035 00036 /*! 00037 * \brief high-performance interface to send and receive raw 00038 * ethernet frames with out-of-order retirement of received frames. 00039 * 00040 * On many systems it should be possible to implement this on top of libpcap 00041 * 00042 * \internal 00043 */ 00044 class eth_buffer : boost::noncopyable 00045 { 00046 00047 int d_fd; // socket file descriptor 00048 uint8_t d_mac[6]; // our mac address 00049 bool d_using_tpring; // using kernel mapped packet ring 00050 size_t d_buflen; // length of our buffer 00051 uint8_t *d_buf; // packet ring 00052 unsigned int d_frame_nr; // max frames on ring 00053 size_t d_frame_size; // frame storage size 00054 unsigned int d_head; // pointer to next frame 00055 00056 std::vector<uint8_t *> d_ring; // pointers into buffer 00057 std::auto_ptr<ethernet> d_ethernet; // our underlying interface 00058 00059 bool frame_available(); 00060 00061 void inc_head() 00062 { 00063 if (d_head + 1 >= d_frame_nr) 00064 d_head = 0; 00065 else 00066 d_head = d_head + 1; 00067 } 00068 00069 00070 public: 00071 00072 enum result { 00073 EB_OK, //< everything's fine 00074 EB_ERROR, //< A non-recoverable error occurred 00075 EB_WOULD_BLOCK, //< A timeout of 0 was specified and nothing was ready 00076 EB_TIMED_OUT, //< The timeout expired before anything was ready 00077 }; 00078 00079 static const unsigned int MAX_PKTLEN = 1512; 00080 static const unsigned int MIN_PKTLEN = 64; 00081 00082 /*! 00083 * \param rx_bufsize is a hint as to the number of bytes of memory 00084 * to allocate for received ethernet frames (0 -> reasonable default) 00085 */ 00086 eth_buffer(size_t rx_bufsize = 0); 00087 ~eth_buffer(); 00088 00089 /*! 00090 * \brief open the specified interface 00091 * 00092 * \param ifname ethernet interface name, e.g., "eth0" 00093 * \param protocol is the ethertype protocol number in network order. 00094 * Use 0 to receive all protocols. 00095 */ 00096 bool open(const std::string &ifname, int protocol); 00097 00098 /*! 00099 * \brief close the interface 00100 */ 00101 bool close(); 00102 00103 /*! 00104 * \brief attach packet filter to socket to restrict which packets read sees. 00105 * \param pf the packet filter 00106 */ 00107 bool attach_pktfilter(pktfilter *pf); 00108 00109 /*! 00110 * \brief return 6 byte string containing our MAC address 00111 */ 00112 const uint8_t *mac() const { return d_mac; } 00113 00114 /*! 00115 * \brief Call \p f for each frame in the receive buffer. 00116 * \param f is the frame data handler 00117 * \param timeout (in ms) controls behavior when there are no frames to read 00118 * 00119 * If \p timeout is 0, rx_frames will not wait for frames if none are 00120 * available, and f will not be invoked. If \p timeout is -1 (the 00121 * default), rx_frames will block indefinitely until frames are 00122 * available. If \p timeout is positive, it indicates the number of 00123 * milliseconds to wait for a frame to become available. Once the 00124 * timeout has expired, rx_frames will return, f never having been 00125 * invoked. 00126 * 00127 * \p f will be called on each ethernet frame that is available. 00128 * \p f returns a bit mask with one of the following set or cleared: 00129 * 00130 * data_handler::KEEP - hold onto the frame and present it again during 00131 * the next call to rx_frames, otherwise discard it 00132 * 00133 * data_handler::DONE - return from rx_frames now even though more frames 00134 * might be available; otherwise continue if more 00135 * frames are ready. 00136 * 00137 * The idea of holding onto a frame for the next iteration allows 00138 * the caller to scan the received packet stream for particular 00139 * classes of frames (such as command replies) leaving the rest 00140 * intact. On the next call all kept frames, followed by any new 00141 * frames received, will be presented in order to \p f. 00142 * See usrp2.cc for an example of the pattern. 00143 * 00144 * \returns EB_OK if at least one frame was received 00145 * \returns EB_WOULD_BLOCK if \p timeout is 0 and the call would have blocked 00146 * \returns EB_TIMED_OUT if timeout occurred 00147 * \returns EB_ERROR if there was an unrecoverable error. 00148 */ 00149 result rx_frames(data_handler *f, int timeout=-1); 00150 00151 /* 00152 * \brief Release frame from buffer 00153 * 00154 * Call to release a frame previously held by a data_handler::KEEP. 00155 * The pointer may be offset from the base of the frame up to its length. 00156 */ 00157 void release_frame(void *p); 00158 00159 /* 00160 * \brief Write an ethernet frame to the interface. 00161 * 00162 * \param base points to the beginning of the frame (the 14-byte ethernet header). 00163 * \param len is the length of the frame in bytes. 00164 * \param flags is 0 or the bitwise-or of values from eth_flags 00165 * 00166 * The frame must begin with a 14-byte ethernet header. 00167 * 00168 * \returns EB_OK if the frame was successfully enqueued. 00169 * \returns EB_WOULD_BLOCK if flags contains EF_DONT_WAIT and the call would have blocked. 00170 * \returns EB_ERROR if there was an unrecoverable error. 00171 */ 00172 result tx_frame(const void *base, size_t len, int flags=0); 00173 00174 /* 00175 * \brief Write an ethernet frame to the interface using scatter/gather. 00176 * 00177 * \param iov points to an array of iovec structs 00178 * \param iovcnt is the number of entries 00179 * \param flags is 0 or the bitwise-or of values from eth_flags 00180 * 00181 * The frame must begin with a 14-byte ethernet header. 00182 * 00183 * \returns EB_OK if the frame was successfully enqueued. 00184 * \returns EB_WOULD_BLOCK if flags contains EF_DONT_WAIT and the call would have blocked. 00185 * \returns EB_ERROR if there was an unrecoverable error. 00186 */ 00187 result tx_framev(const eth_iovec *iov, int iovcnt, int flags=0); 00188 00189 /* 00190 * \brief Returns maximum possible number of frames in buffer 00191 */ 00192 unsigned int max_frames() const { return d_frame_nr; } 00193 00194 }; 00195 00196 }; // namespace usrp2 00197 00198 #endif /* INCLUDED_USRP2_ETH_BUFFER_H */