From 1aef83037f6a9988b06a547710afbbe5ce815459 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 23 Mar 2010 18:17:47 -0700 Subject: Added example app to receive timed samples. Added useful calls to simple device. Fixed vrt frac time usage (wrong word). --- host/lib/transport/vrt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/transport') diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index a06b5bf21..cc46b2381 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -42,8 +42,8 @@ void vrt::pack( if(metadata.has_time_spec){ vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp header_buff[num_header_words32++] = htonl(metadata.time_spec.secs); - header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks); header_buff[num_header_words32++] = 0; //unused part of fractional seconds + header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks); } vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; @@ -99,8 +99,8 @@ void vrt::unpack( if (vrt_hdr_word & (0x3 << 20)){ //fractional time metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]); num_header_words32++; //unused part of fractional seconds + metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]); } size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0; -- cgit v1.2.3 From af586ae149fe6f7aa12d4d6766e4216f3f00d1c0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Mar 2010 18:36:16 -0700 Subject: Overhaullllllled the way we do streaming. There is an odd bug where a zero length command (now, no chain) used to stop the streaming. Now it seems to do the reverse... must investigate. Made all clock configuration into enums. The strings were painful and there cant be that many variations that enums cant cover them. The enums will make more sense to developers than mystery strings. --- firmware/microblaze/apps/txrx.c | 174 ++++++++++++++++-------------- firmware/microblaze/lib/memory_map.h | 3 +- host/examples/rx_timed_samples.cpp | 14 ++- host/include/uhd/props.hpp | 2 - host/include/uhd/simple_device.hpp | 4 +- host/include/uhd/time_spec.hpp | 10 +- host/include/uhd/types.hpp | 52 +++++++-- host/lib/simple_device.cpp | 13 +-- host/lib/time_spec.cpp | 5 - host/lib/transport/udp_zero_copy_asio.cpp | 2 +- host/lib/types.cpp | 15 ++- host/lib/usrp/usrp2/dsp_impl.cpp | 42 +++----- host/lib/usrp/usrp2/fw_common.h | 16 +-- host/lib/usrp/usrp2/io_impl.cpp | 8 +- host/lib/usrp/usrp2/mboard_impl.cpp | 77 +++++++------ host/lib/usrp/usrp2/usrp2_impl.hpp | 10 +- 16 files changed, 233 insertions(+), 214 deletions(-) (limited to 'host/lib/transport') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 5eec99c4f..a2e3f0430 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -54,11 +54,6 @@ #define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) -#if (FW_SETS_SEQNO) -static int fw_seqno; // used when f/w is filling in sequence numbers -#endif - - /* * Full duplex Tx and Rx between ethernet and DSP pipelines * @@ -127,18 +122,14 @@ dbsm_t dsp_rx_sm; // the state machine // The mac address of the host we're sending to. eth_mac_addr_t host_mac_addr; -#define TIME_NOW ((uint32_t)(~0)) - -// variables for streaming mode - -static bool streaming_p = false; -static unsigned int streaming_items_per_frame = 0; -static uint32_t time_secs = TIME_NOW; -static uint32_t time_ticks = TIME_NOW; -static int streaming_frame_count = 0; +//controls continuous streaming... +static bool auto_reload_command = false; +static size_t streaming_items_per_frame = 0; +static int streaming_frame_count = 0; #define FRAMES_PER_CMD 2 -bool is_streaming(void){ return streaming_p; } +static void setup_network(void); +static void setup_vrt(void); // ---------------------------------------------------------------- // the fast-path setup global variables @@ -159,6 +150,9 @@ void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ + //store the 2nd word as the following: + streaming_items_per_frame = ((uint32_t *)payload)[1]; + //its a tiny payload, load the fast-path variables fp_mac_addr_src = *ethernet_mac_addr(); arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); @@ -176,6 +170,24 @@ void handle_udp_data_packet( print_ip_addr(&fp_socket_dst.addr); newline(); printf(" destination udp port: %d\n", fp_socket_dst.port); newline(); + + //setup network and vrt + setup_network(); + setup_vrt(); + + // kick off the state machine + dbsm_start(&dsp_rx_sm); + +} + +static void inline issue_stream_command(size_t nsamps, bool now, bool chain, uint32_t secs, uint32_t ticks, bool start){ + //printf("Stream cmd: nsamps %d, now %d, chain %d, secs %u, ticks %u\n", (int)nsamps, now, chain, secs, ticks); + sr_rx_ctrl->cmd = MK_RX_CMD(nsamps, now, chain); + + if (start) dbsm_start(&dsp_rx_sm); + + sr_rx_ctrl->time_secs = secs; + sr_rx_ctrl->time_ticks = ticks; // enqueue command } #define OTW_GPIO_BANK_TO_NUM(bank) \ @@ -443,20 +455,68 @@ void handle_udp_ctrl_packet( ctrl_data_out.id = USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE; break; - case USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO: - time_secs = ctrl_data_in->data.streaming.secs; - time_ticks = ctrl_data_in->data.streaming.ticks; - streaming_items_per_frame = ctrl_data_in->data.streaming.samples; + /******************************************************************* + * Streaming + ******************************************************************/ + case USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO:{ + + //issue two commands and set the auto-reload flag + if (ctrl_data_in->data.stream_cmd.continuous){ + printf("Setting up continuous streaming...\n"); + auto_reload_command = true; + streaming_frame_count = FRAMES_PER_CMD; + + issue_stream_command( + streaming_items_per_frame * FRAMES_PER_CMD, + (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now + true, //chain + ctrl_data_in->data.stream_cmd.secs, + ctrl_data_in->data.stream_cmd.ticks, + true //start + ); + + issue_stream_command( + streaming_items_per_frame * FRAMES_PER_CMD, + true, //now + true, //chain + 0, 0, //time does not matter + false + ); - if (ctrl_data_in->data.streaming.enabled == 0){ - stop_rx_cmd(); } + + //issue regular stream commands (split commands if too large) else{ - start_rx_streaming_cmd(); - } + auto_reload_command = false; + size_t num_samps = ctrl_data_in->data.stream_cmd.num_samps; + if (num_samps == 0) num_samps = 1; //FIXME hack, zero is used when stopping continuous streaming but it somehow makes it inifinite + + bool chain = num_samps > MAX_SAMPLES_PER_CMD; + issue_stream_command( + (chain)? streaming_items_per_frame : num_samps, //nsamps + (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now + chain, //chain + ctrl_data_in->data.stream_cmd.secs, + ctrl_data_in->data.stream_cmd.ticks, + false + ); - ctrl_data_out.id = USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE; + //handle rest of the samples that did not fit into one cmd + while(chain){ + num_samps -= MAX_SAMPLES_PER_CMD; + chain = num_samps > MAX_SAMPLES_PER_CMD; + issue_stream_command( + (chain)? streaming_items_per_frame : num_samps, //nsamps + true, //now + chain, //chain + 0, 0, //time does not matter + false + ); + } + } + ctrl_data_out.id = USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE; break; + } /******************************************************************* * DUC @@ -531,7 +591,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) // In the future, a hardware state machine will do this... if ( //warning! magic numbers approaching.... (((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) && - ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != 0) + ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != USRP2_INVALID_VRT_HEADER) ) return false; //test if its an ip recovery packet @@ -557,7 +617,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) //------------------------------------------------------------------ -static uint16_t get_vrt_packet_words(void){ +static size_t get_vrt_packet_words(void){ return streaming_items_per_frame + \ USRP2_HOST_RX_VRT_HEADER_WORDS32 + \ USRP2_HOST_RX_VRT_TRAILER_WORDS32; @@ -567,9 +627,7 @@ static bool vrt_has_trailer(void){ return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0; } -void -restart_streaming(void) -{ +static void setup_vrt(void){ // setup RX DSP regs sr_rx_ctrl->nsamples_per_pkt = streaming_items_per_frame; sr_rx_ctrl->nchannels = 1; @@ -582,26 +640,6 @@ restart_streaming(void) ); sr_rx_ctrl->vrt_stream_id = 0; sr_rx_ctrl->vrt_trailer = 0; - - streaming_p = true; - streaming_frame_count = FRAMES_PER_CMD; - - sr_rx_ctrl->cmd = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - (time_ticks==TIME_NOW)?1:0, 1); // conditionally set "now" bit, set "chain" bit - - // kick off the state machine - dbsm_start(&dsp_rx_sm); - - sr_rx_ctrl->time_secs = time_secs; - sr_rx_ctrl->time_ticks = time_ticks; // enqueue first of two commands - - // make sure this one and the rest have the "now" and "chain" bits set. - sr_rx_ctrl->cmd = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, 1, 1); - - sr_rx_ctrl->time_secs = 0; - sr_rx_ctrl->time_ticks = 0; // enqueue second command } /* @@ -630,19 +668,15 @@ link_changed_callback(int speed) printf("\neth link changed: speed = %d\n", speed); } -void -start_rx_streaming_cmd(void) -{ - /* - * Construct ethernet header and preload into two buffers - */ +static void setup_network(void){ + //setup header and load into two buffers struct { uint32_t ctrl_word; } mem _AL4; memset(&mem, 0, sizeof(mem)); - printf("samples per frame: %d\n", streaming_items_per_frame); - printf("words in a vrt packet %d\n", get_vrt_packet_words()); + printf("items per frame: %d\n", (int)streaming_items_per_frame); + printf("words in a vrt packet %d\n", (int)get_vrt_packet_words()); mem.ctrl_word = get_vrt_packet_words()*sizeof(uint32_t) | 1 << 16; memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem)); @@ -678,26 +712,6 @@ start_rx_streaming_cmd(void) sr_udp_sm->udp_hdr.dst_port = fp_socket_dst.port; sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum - - if (FW_SETS_SEQNO) - fw_seqno = 0; - - restart_streaming(); -} - -void -stop_rx_cmd(void) -{ - if (is_streaming()){ - streaming_p = false; - - // no samples, "now", not chained - sr_rx_ctrl->cmd = MK_RX_CMD(0, 1, 0); - - sr_rx_ctrl->time_secs = 0; - sr_rx_ctrl->time_ticks = 0; // enqueue command - } - } #if (FW_SETS_SEQNO) @@ -713,10 +727,10 @@ bool fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false { // queue up another rx command when required - if (streaming_p && --streaming_frame_count == 0){ + if (auto_reload_command && --streaming_frame_count == 0){ streaming_frame_count = FRAMES_PER_CMD; sr_rx_ctrl->time_secs = 0; - sr_rx_ctrl->time_ticks = 0; + sr_rx_ctrl->time_ticks = 0; //enqueue last command } return false; // we didn't handle the packet @@ -820,7 +834,7 @@ main(void) // FIXME Figure out how to handle this robustly. // Any buffers that are emptying should be allowed to drain... - if (streaming_p){ + if (auto_reload_command){ // restart_streaming(); // FIXME report error } diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h index bb6a1036d..fed1e5259 100644 --- a/firmware/microblaze/lib/memory_map.h +++ b/firmware/microblaze/lib/memory_map.h @@ -525,8 +525,9 @@ typedef struct { volatile uint32_t pad[7]; // Make each structure 16 elements long } sr_rx_ctrl_t; +#define MAX_SAMPLES_PER_CMD 0x3fffffff #define MK_RX_CMD(nsamples, now, chain) \ - ((((now) & 0x1) << 31) | ((chain & 0x1) << 30) | ((nsamples) & 0x3fffffff)) + ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | ((nsamples) & 0x3fffffff)) #define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 97f75647e..7d58187cd 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -65,9 +65,14 @@ int main(int argc, char *argv[]){ //setup streaming std::cout << std::endl; - std::cout << boost::format("Begin streaming %u seconds in the future...") - % seconds_in_future << std::endl; - sdev->set_streaming_at(uhd::time_spec_t(seconds_in_future)); + std::cout << boost::format("Begin streaming %u samples, %d seconds in the future...") + % total_num_samps % seconds_in_future << std::endl; + uhd::stream_cmd_t stream_cmd; + stream_cmd.stream_now = false; + stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); + stream_cmd.continuous = false; + stream_cmd.num_samps = total_num_samps; + sdev->issue_stream_cmd(stream_cmd); //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples @@ -83,8 +88,7 @@ int main(int argc, char *argv[]){ num_acc_samps += num_rx_samps; } - //finished, stop streaming - sdev->set_streaming(false); + //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return 0; diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 41e0eff63..01746f853 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -76,8 +76,6 @@ namespace uhd{ MBOARD_PROP_TX_DBOARD, //ro, wax::obj MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t - MBOARD_PROP_PPS_SOURCE_NAMES, //ro, prop_names_t - MBOARD_PROP_REF_SOURCE_NAMES, //ro, prop_names_t MBOARD_PROP_TIME_NOW, //wo, time_spec_t MBOARD_PROP_TIME_NEXT_PPS //wo, time_spec_t }; diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index 035757936..bbe0258c7 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -51,9 +51,7 @@ public: /******************************************************************* * Streaming ******************************************************************/ - virtual void set_streaming_at(const time_spec_t &time_spec) = 0; - virtual void set_streaming(bool enb) = 0; - virtual bool get_streaming(void) = 0; + virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; /******************************************************************* * RX methods diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp index c1e7cf3a1..e863746ba 100644 --- a/host/include/uhd/time_spec.hpp +++ b/host/include/uhd/time_spec.hpp @@ -34,18 +34,12 @@ namespace uhd{ boost::uint32_t secs; boost::uint32_t ticks; - /*! - * Create a time_spec_t that holds a wildcard time. - * This will have implementation-specific meaning. - */ - time_spec_t(void); - /*! * Create a time_spec_t from seconds and ticks. - * \param new_secs the new seconds + * \param new_secs the new seconds (default = 0) * \param new_ticks the new ticks (default = 0) */ - time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks = 0); + time_spec_t(boost::uint32_t new_secs = 0, boost::uint32_t new_ticks = 0); /*! * Create a time_spec_t from boost posix time. diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types.hpp index 1439f57a1..3ad3dae82 100644 --- a/host/include/uhd/types.hpp +++ b/host/include/uhd/types.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_TYPES_HPP #include +#include #include namespace uhd{ @@ -66,18 +67,53 @@ namespace uhd{ * Clock configuration settings: * The source for the 10MHz reference clock. * The source and polarity for the PPS clock. - * Possible settings for the reference and pps source - * are implementation specific motherboard properties. - * See the MBOARD_PROP_XXX_SOURCE_NAMES properties. */ - struct clock_config_t{ - enum polarity_t {POLARITY_NEG, POLARITY_POS}; - std::string ref_source; - std::string pps_source; - polarity_t pps_polarity; + struct UHD_API clock_config_t{ + enum ref_source_t { + REF_INT, //internal reference + REF_SMA, //external sma port + REF_MIMO //mimo cable (usrp2 only) + } ref_source; + enum pps_source_t { + PPS_INT, //there is no internal + PPS_SMA, //external sma port + PPS_MIMO //mimo cable (usrp2 only) + } pps_source; + enum pps_polarity_t { + PPS_NEG, //negative edge + PPS_POS //positive edge + } pps_polarity; clock_config_t(void); }; + /*! + * Command struct for configuration and control of streaming: + * + * A stream command defines how the device sends samples to the host. + * Streaming is controlled by submitting a stream command to the rx dsp. + * Granular control over what the device streams to the host can be + * achieved through submission of multiple (carefully-crafted) commands. + * + * The stream_now parameter controls when the stream begins. + * When true, the device will begin streaming ASAP. When false, + * the device will begin streaming at a time specified by time_spec. + * + * The continuous parameter controls the number of samples received. + * When true, the device continues streaming indefinitely. When false, + * the device will stream the number of samples specified by num_samps. + * + * Standard usage case: + * To start continuous streaming, set stream_now to true and continuous to true. + * To end continuous streaming, set stream_now to true and continuous to false. + */ + struct UHD_API stream_cmd_t{ + bool stream_now; + time_spec_t time_spec; + bool continuous; + size_t num_samps; + stream_cmd_t(void); + }; + } //namespace uhd #endif /* INCLUDED_UHD_TYPES_HPP */ diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index bb7ddfc68..a25cb12e0 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -167,17 +167,8 @@ public: /******************************************************************* * Streaming ******************************************************************/ - void set_streaming_at(const time_spec_t &time_spec){ - _rx_ddc[std::string("stream_at")] = time_spec; - _rx_ddc[std::string("enabled")] = true; - } - - void set_streaming(bool enb){ - _rx_ddc[std::string("enabled")] = enb; - } - - bool get_streaming(void){ - return _rx_ddc[std::string("enabled")].as(); + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + _rx_ddc[std::string("stream_cmd")] = stream_cmd; } /******************************************************************* diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp index 210010394..98bf28077 100644 --- a/host/lib/time_spec.cpp +++ b/host/lib/time_spec.cpp @@ -19,11 +19,6 @@ using namespace uhd; -time_spec_t::time_spec_t(void){ - secs = ~0; - ticks = ~0; -} - time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){ secs = new_secs; ticks = new_ticks; diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 219ae8720..9436f2a13 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -115,7 +115,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){ //implement timeout through polling and sleeping boost::asio::deadline_timer timer(_socket->get_io_service()); - timer.expires_from_now(boost::posix_time::milliseconds(50)); + timer.expires_from_now(boost::posix_time::milliseconds(100)); while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } diff --git a/host/lib/types.cpp b/host/lib/types.cpp index f8a9a9b36..273f87a2d 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -51,7 +51,16 @@ tune_result_t::tune_result_t(void){ * clock config **********************************************************************/ clock_config_t::clock_config_t(void){ - ref_source = ""; //not a valid setting - pps_source = ""; //not a valid setting - pps_polarity = POLARITY_NEG; + ref_source = REF_INT, + pps_source = PPS_INT, + pps_polarity = PPS_NEG; +} + +/*********************************************************************** + * stream command + **********************************************************************/ +stream_cmd_t::stream_cmd_t(void){ + stream_now = true; + continuous = false; + num_samps = 0; } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 34cce0afb..44f654863 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -63,9 +63,8 @@ void usrp2_impl::init_ddc_config(void){ _ddc_freq = 0; update_ddc_config(); - _ddc_stream_at = time_spec_t(); - _ddc_enabled = false; - update_ddc_enabled(); + //initial command that kills streaming (in case if was left on) + //issue_ddc_stream_cmd(TODO) } void usrp2_impl::update_ddc_config(void){ @@ -86,21 +85,19 @@ void usrp2_impl::update_ddc_config(void){ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE); } -void usrp2_impl::update_ddc_enabled(void){ +void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ //setup the out data usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO); - out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0; - out_data.data.streaming.secs = htonl(_ddc_stream_at.secs); - out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks); - out_data.data.streaming.samples = htonl(_max_rx_samples_per_packet); + out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO); + out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0; + out_data.data.stream_cmd.continuous = (stream_cmd.continuous)? 1 : 0; + out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs); + out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks); + out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE); - - //clear the stream at time spec (it must be set for the next round of enable/disable) - _ddc_stream_at = time_spec_t(); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); } /*********************************************************************** @@ -120,8 +117,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ ("decim") ("decims") ("freq") - ("enabled") - ("stream_at") + ("stream_cmd") ; val = others; } @@ -147,10 +143,6 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ val = _ddc_freq; return; } - else if (key_name == "enabled"){ - val = _ddc_enabled; - return; - } throw std::invalid_argument(str( boost::format("error getting: unknown key with name %s") % key_name @@ -178,16 +170,8 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ update_ddc_config(); return; } - else if (key_name == "enabled"){ - bool new_enabled = val.as(); - _ddc_enabled = new_enabled; //shadow - update_ddc_enabled(); - return; - } - else if (key_name == "stream_at"){ - time_spec_t new_stream_at = val.as(); - _ddc_stream_at = new_stream_at; //shadow - //update_ddc_enabled(); //dont update from here + else if (key_name == "stream_cmd"){ + issue_ddc_stream_cmd(val.as()); return; } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 7fcae6fb2..30fee6c32 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -32,6 +32,9 @@ extern "C" { #define _SINS_ #endif +//used to differentiate control packets over data port +#define USRP2_INVALID_VRT_HEADER 0 + // size of the vrt header and trailer to the host #define USRP2_HOST_RX_VRT_HEADER_WORDS32 5 #define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present @@ -90,8 +93,8 @@ typedef enum{ USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO, USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE, - USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO, - USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE, + USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO, + USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE, USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO, USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE, @@ -186,12 +189,13 @@ typedef struct{ _SINS_ uint32_t scale_iq; } ddc_args; struct { - _SINS_ uint8_t enabled; - _SINS_ uint8_t _pad[3]; + _SINS_ uint8_t now; //stream now? + _SINS_ uint8_t continuous; //auto-reload commmands? + _SINS_ uint8_t _pad[2]; _SINS_ uint32_t secs; _SINS_ uint32_t ticks; - _SINS_ uint32_t samples; - } streaming; + _SINS_ uint32_t num_samps; + } stream_cmd; struct { _SINS_ uint32_t freq_word; _SINS_ uint32_t interp; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index df0736863..280f124d2 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -41,8 +41,12 @@ void usrp2_impl::io_init(void){ _rx_copy_buff = asio::buffer("", 0); //send a small data packet so the usrp2 knows the udp source port - boost::uint32_t zero_data = 0; - _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data))); + //and the maximum number of lines (32 bit words) per packet + boost::uint32_t data[2] = { + htonl(USRP2_INVALID_VRT_HEADER), + htonl(_max_rx_samples_per_packet) + }; + _data_transport->send(asio::buffer(&data, sizeof(data))); } #define unrolled_loop(__inst, __len){ \ diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index cbca8eec7..c56782c4b 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -35,27 +35,10 @@ void usrp2_impl::mboard_init(void){ } void usrp2_impl::init_clock_config(void){ - //init the ref source clock config - _ref_source_dict = boost::assign::map_list_of - ("int", USRP2_REF_SOURCE_INT) - ("sma", USRP2_REF_SOURCE_SMA) - ("mimo", USRP2_REF_SOURCE_MIMO) - ; - _clock_config.ref_source = "int"; - - //init the pps source clock config - _pps_source_dict = boost::assign::map_list_of - ("sma", USRP2_PPS_SOURCE_SMA) - ("mimo", USRP2_PPS_SOURCE_MIMO) - ; - _clock_config.pps_source = "sma"; - - //init the pps polarity clock config - _pps_polarity_dict = boost::assign::map_list_of - (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS) - (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG) - ; - _clock_config.pps_polarity = clock_config_t::POLARITY_NEG; + //setup the clock configuration settings + _clock_config.ref_source = clock_config_t::REF_INT; + _clock_config.pps_source = clock_config_t::PPS_SMA; + _clock_config.pps_polarity = clock_config_t::PPS_NEG; //update the clock config (sends a control packet) update_clock_config(); @@ -65,9 +48,35 @@ void usrp2_impl::update_clock_config(void){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO); - out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source]; - out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source]; - out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity]; + + //translate ref source enums + switch(_clock_config.ref_source){ + case clock_config_t::REF_INT: + out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_INT; break; + case clock_config_t::REF_SMA: + out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_SMA; break; + case clock_config_t::REF_MIMO: + out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_MIMO; break; + default: throw std::runtime_error("usrp2: unhandled clock configuration ref source"); + } + + //translate pps source enums + switch(_clock_config.pps_source){ + case clock_config_t::PPS_SMA: + out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_SMA; break; + case clock_config_t::PPS_MIMO: + out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_MIMO; break; + default: throw std::runtime_error("usrp2: unhandled clock configuration pps source"); + } + + //translate pps polarity enums + switch(_clock_config.pps_polarity){ + case clock_config_t::PPS_POS: + out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_POS; break; + case clock_config_t::PPS_NEG: + out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_NEG; break; + default: throw std::runtime_error("usrp2: unhandled clock configuration pps polarity"); + } //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -184,14 +193,6 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = _clock_config; return; - case MBOARD_PROP_PPS_SOURCE_NAMES: - val = prop_names_t(_pps_source_dict.get_keys()); - return; - - case MBOARD_PROP_REF_SOURCE_NAMES: - val = prop_names_t(_ref_source_dict.get_keys()); - return; - case MBOARD_PROP_TIME_NOW: case MBOARD_PROP_TIME_NEXT_PPS: throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard"); @@ -234,13 +235,9 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ - case MBOARD_PROP_CLOCK_CONFIG:{ - clock_config_t clock_config = val.as(); - assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source"); - assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source"); - _clock_config = clock_config; //shadow - update_clock_config(); - } + case MBOARD_PROP_CLOCK_CONFIG: + _clock_config = val.as(); + update_clock_config(); return; case MBOARD_PROP_TIME_NOW:{ @@ -264,8 +261,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ case MBOARD_PROP_RX_DBOARD_NAMES: case MBOARD_PROP_TX_DBOARD: case MBOARD_PROP_TX_DBOARD_NAMES: - case MBOARD_PROP_PPS_SOURCE_NAMES: - case MBOARD_PROP_REF_SOURCE_NAMES: throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard"); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 55ac0b192..2794cc666 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -146,11 +145,6 @@ private: void update_clock_config(void); void set_time_spec(const uhd::time_spec_t &time_spec, bool now); - //mappings from clock config strings to over the wire enums - uhd::dict _ref_source_dict; - uhd::dict _pps_source_dict; - uhd::dict _pps_polarity_dict; - //rx and tx dboard methods and objects uhd::usrp::dboard_manager::sptr _dboard_manager; void dboard_init(void); @@ -178,11 +172,9 @@ private: std::vector _allowed_decim_and_interp_rates; size_t _ddc_decim; uhd::freq_t _ddc_freq; - bool _ddc_enabled; - uhd::time_spec_t _ddc_stream_at; void init_ddc_config(void); void update_ddc_config(void); - void update_ddc_enabled(void); + void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd); //methods and shadows for the duc dsp size_t _duc_interp; -- cgit v1.2.3 From 08f6b21ce7cc4aa4069b4461785fc7173bed2998 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Mar 2010 11:45:56 -0700 Subject: added interface address discovery --- host/include/uhd/transport/CMakeLists.txt | 1 + host/include/uhd/transport/if_addrs.hpp | 47 ++++ host/include/uhd/transport/smart_buffer.hpp | 2 +- host/include/uhd/transport/udp_simple.hpp | 2 +- host/include/uhd/transport/udp_zero_copy.hpp | 2 +- host/lib/CMakeLists.txt | 15 +- host/lib/transport/if_addrs.cpp | 343 +++++++++++++++++++++++++++ host/lib/transport/udp_simple.cpp | 1 + host/lib/transport/udp_zero_copy_asio.cpp | 1 + host/lib/usrp/usrp2/usrp2_impl.cpp | 20 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + 11 files changed, 429 insertions(+), 6 deletions(-) create mode 100644 host/include/uhd/transport/if_addrs.hpp create mode 100644 host/lib/transport/if_addrs.cpp (limited to 'host/lib/transport') diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 75b07c540..14b5ccd29 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,7 @@ INSTALL(FILES + if_addrs.hpp smart_buffer.hpp udp_simple.hpp udp_zero_copy.hpp diff --git a/host/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp new file mode 100644 index 000000000..fbbb35e1d --- /dev/null +++ b/host/include/uhd/transport/if_addrs.hpp @@ -0,0 +1,47 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_UHD_IFADDRS_HPP +#define INCLUDED_UHD_IFADDRS_HPP + +#include +#include +#include + +namespace uhd{ namespace transport{ + + /*! + * The address for a network interface. + */ + struct UHD_API if_addrs_t{ + std::string inet; + std::string mask; + std::string bcast; + if_addrs_t(void); + }; + + /*! + * Get a list of network interface addresses. + * The internal implementation is system-dependent. + * \return a vector of if addrs + */ + UHD_API std::vector get_if_addrs(void); + +}} //namespace + + +#endif /* INCLUDED_UHD_IFADDRS_HPP */ diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp index 9e1032feb..a9bc259e9 100644 --- a/host/include/uhd/transport/smart_buffer.hpp +++ b/host/include/uhd/transport/smart_buffer.hpp @@ -18,7 +18,7 @@ #ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP #define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP -#include +#include #include #include diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index 40e60d091..793ec4fd7 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP #include -#include +#include #include #include diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index 03d89b3a5..0441a8e74 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 22fbde265..4dd638336 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -28,6 +28,7 @@ SET(libuhd_sources time_spec.cpp types.cpp wax.cpp + transport/if_addrs.cpp transport/udp_simple.cpp transport/vrt.cpp usrp/dboard/basic.cpp @@ -60,7 +61,6 @@ LIST(APPEND libuhd_sources # Setup defines for module loading ######################################################################## INCLUDE(CheckIncludeFileCXX) - CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H) @@ -74,6 +74,19 @@ ELSE(HAVE_DLFCN_H) MESSAGE(STATUS "Module loading not supported...") ENDIF(HAVE_DLFCN_H) +######################################################################## +# Setup defines for interface address discovery +######################################################################## +INCLUDE(CheckIncludeFileCXX) +CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H) + +IF(HAVE_IFADDRS_H) + MESSAGE(STATUS "Interface address discovery supported through getifaddrs...") + ADD_DEFINITIONS(-DHAVE_IFADDRS_H) +ELSE(HAVE_IFADDRS_H) + MESSAGE(STATUS "Interface address discovery not supported...") +ENDIF(HAVE_IFADDRS_H) + ######################################################################## # Setup libuhd library ######################################################################## diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp new file mode 100644 index 000000000..d3ea448fd --- /dev/null +++ b/host/lib/transport/if_addrs.cpp @@ -0,0 +1,343 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include + +uhd::transport::if_addrs_t::if_addrs_t(void){ + /* NOP */ +} + +/*********************************************************************** + * Interface address discovery through ifaddrs api + **********************************************************************/ +#ifdef HAVE_IFADDRS_H +#include +#include + +static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ + if (addr->sa_family == AF_INET) return boost::asio::ip::address_v4(ntohl( + reinterpret_cast(addr)->sin_addr.s_addr + )); + return boost::asio::ip::address_v4::any(); +} + +static bool ifaddrs_valid(const struct ifaddrs *ifaddrs){ + return ( + ifaddrs->ifa_addr->sa_family == AF_INET and + sockaddr_to_ip_addr(ifaddrs->ifa_addr) != boost::asio::ip::address_v4::loopback() + ); +} + +std::vector uhd::transport::get_if_addrs(void){ + std::vector if_addrs; + struct ifaddrs *ifap; + if (getifaddrs(&ifap) == 0){ + for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){ + if (not ifaddrs_valid(iter)) continue; + if_addrs_t if_addr; + if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string(); + if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string(); + if_addr.bcast = sockaddr_to_ip_addr(iter->ifa_broadaddr).to_string(); + if_addrs.push_back(if_addr); + } + freeifaddrs(ifap); + } + return if_addrs; +} + +/*********************************************************************** + * Interface address discovery through windows api (TODO) + **********************************************************************/ +//#elif HAVE_XXX_H + +/*********************************************************************** + * Interface address discovery not included + **********************************************************************/ +#else /* HAVE_IFADDRS_H */ + +std::vector uhd::transport::get_if_addrs(void){ + return std::vector(); +} + +#endif /* HAVE_IFADDRS_H */ + +//////////////////////////////////////////////////////////////////////// +// How to extract the ip address: unix/windows +// http://www.developerweb.net/forum/showthread.php?t=5085 +//////////////////////////////////////////////////////////////////////// + +/* +#include + +#ifdef WIN32 +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +typedef unsigned long uint32; + +#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__) +# define USE_GETIFADDRS 1 +# include +static uint32 SockAddrToUint32(struct sockaddr * a) +{ + return ((a)&&(a->sa_family == AF_INET)) ? ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0; +} +#endif + +// convert a numeric IP address into its string representation +static void Inet_NtoA(uint32 addr, char * ipbuf) +{ + sprintf(ipbuf, "%li.%li.%li.%li", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); +} + +// convert a string represenation of an IP address into its numeric equivalent +static uint32 Inet_AtoN(const char * buf) +{ + // net_server inexplicably doesn't have this function; so I'll just fake it + uint32 ret = 0; + int shift = 24; // fill out the MSB first + bool startQuad = true; + while((shift >= 0)&&(*buf)) + { + if (startQuad) + { + unsigned char quad = (unsigned char) atoi(buf); + ret |= (((uint32)quad) << shift); + shift -= 8; + } + startQuad = (*buf == '.'); + buf++; + } + return ret; +} + +static void PrintNetworkInterfaceInfos() +{ +#if defined(USE_GETIFADDRS) + // BSD-style implementation + struct ifaddrs * ifap; + if (getifaddrs(&ifap) == 0) + { + struct ifaddrs * p = ifap; + while(p) + { + uint32 ifaAddr = SockAddrToUint32(p->ifa_addr); + uint32 maskAddr = SockAddrToUint32(p->ifa_netmask); + uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr); + if (ifaAddr > 0) + { + char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr); + printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + } + p = p->ifa_next; + } + freeifaddrs(ifap); + } +#elif defined(WIN32) + // Windows XP style implementation + + // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx + // Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable() + // multiple times in order to deal with potential race conditions properly. + MIB_IPADDRTABLE * ipTable = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false); + if (ipRet == ERROR_INSUFFICIENT_BUFFER) + { + free(ipTable); // in case we had previously allocated it + ipTable = (MIB_IPADDRTABLE *) malloc(bufLen); + } + else if (ipRet == NO_ERROR) break; + else + { + free(ipTable); + ipTable = NULL; + break; + } + } + } + + if (ipTable) + { + // Try to get the Adapters-info table, so we can given useful names to the IP + // addresses we are returning. Gotta call GetAdaptersInfo() up to 5 times to handle + // the potential race condition between the size-query call and the get-data call. + // I love a well-designed API :^P + IP_ADAPTER_INFO * pAdapterInfo = NULL; + { + ULONG bufLen = 0; + for (int i=0; i<5; i++) + { + DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen); + if (apRet == ERROR_BUFFER_OVERFLOW) + { + free(pAdapterInfo); // in case we had previously allocated it + pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen); + } + else if (apRet == ERROR_SUCCESS) break; + else + { + free(pAdapterInfo); + pAdapterInfo = NULL; + break; + } + } + } + + for (DWORD i=0; idwNumEntries; i++) + { + const MIB_IPADDRROW & row = ipTable->table[i]; + + // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it + const char * name = NULL; + const char * desc = NULL; + if (pAdapterInfo) + { + IP_ADAPTER_INFO * next = pAdapterInfo; + while((next)&&(name==NULL)) + { + IP_ADDR_STRING * ipAddr = &next->IpAddressList; + while(ipAddr) + { + if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) + { + name = next->AdapterName; + desc = next->Description; + break; + } + ipAddr = ipAddr->Next; + } + next = next->Next; + } + } + char buf[128]; + if (name == NULL) + { + sprintf(buf, "unnamed-%i", i); + name = buf; + } + + uint32 ipAddr = ntohl(row.dwAddr); + uint32 netmask = ntohl(row.dwMask); + uint32 baddr = ipAddr & netmask; + if (row.dwBCastAddr) baddr |= ~netmask; + + char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr); + char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr); + char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr); + printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); + } + + free(pAdapterInfo); + free(ipTable); + } +#else + // Dunno what we're running on here! +# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!" +#endif +} + +int main(int, char **) +{ + PrintNetworkInterfaceInfos(); + return 0; +} +*/ + +//////////////////////////////////////////////////////////////////////// +// How to extract the mac address: linux/windows +// http://old.nabble.com/MAC-Address-td19111197.html +//////////////////////////////////////////////////////////////////////// + +/* +Linux: + +#include +#include +#include +#include +#include +#include +#include + +ifaddrs * ifap = 0; +if(getifaddrs(&ifap) == 0) +{ + ifaddrs * iter = ifap; + while(iter) + { + sockaddr_ll * sal = + reinterpret_cast(iter->ifa_addr); + if(sal->sll_family == AF_PACKET) + { + // get the mac bytes + // copy(sal->sll_addr, + // sal->sll_addr+sal->sll_hallen, + // buffer); + } + iter = iter->ifa_next; + } + freeifaddrs(ifap); +} + +Windows: +#include +#include + +std::vector buf; +DWORD bufLen = 0; +GetAdaptersAddresses(0, 0, 0, 0, &bufLen); +if(bufLen) +{ + buf.resize(bufLen, 0); + IP_ADAPTER_ADDRESSES * ptr = + reinterpret_cast(&buf[0]); + DWORD err = GetAdaptersAddresses(0, 0, 0, ptr, &bufLen); + if(err == NO_ERROR) + { + while(ptr) + { + if(ptr->PhysicalAddressLength) + { + // get the mac bytes + // copy(ptr->PhysicalAddress, + // ptr->PhysicalAddress+ptr->PhysicalAddressLength, + // buffer); + } + ptr = ptr->Next; + } + } +} +*/ diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp index 3c8ecb70d..f339127ad 100644 --- a/host/lib/transport/udp_simple.cpp +++ b/host/lib/transport/udp_simple.cpp @@ -16,6 +16,7 @@ // #include +#include #include #include #include diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 219ae8720..63944b2bf 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 85d73e83a..f04ae8d2c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -15,9 +15,11 @@ // along with this program. If not, see . // +#include +#include #include +#include #include -#include #include #include "usrp2_impl.hpp" @@ -36,7 +38,21 @@ STATIC_BLOCK(register_usrp2_device){ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ device_addrs_t usrp2_addrs; - if (not hint.has_key("addr")) return usrp2_addrs; + //if no address was specified, send a broadcast on each interface + if (not hint.has_key("addr")){ + BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){ + //create a new hint with this broadcast address + device_addr_t new_hint = hint; + new_hint["addr"] = if_addrs.bcast; + + //call discover with the new hint and append results + device_addrs_t new_usrp2_addrs = usrp2::discover(new_hint); + usrp2_addrs.insert(usrp2_addrs.begin(), + new_usrp2_addrs.begin(), new_usrp2_addrs.end() + ); + } + return usrp2_addrs; + } //create a udp transport to communicate //TODO if an addr is not provided, search all interfaces? diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 55ac0b192..a2f454c61 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From d1e67602d21bcf97dbea28206659f3ee1146cf4a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Mar 2010 15:38:12 -0700 Subject: made python app to generate vrt jump tables, seems to run faster... --- host/lib/transport/gen_vrt.py | 206 ++++++++++++++++ host/lib/transport/vrt.cpp | 550 +++++++++++++++++++++++++++++++++++++----- host/utils/usrp2_recovery.py | 16 ++ 3 files changed, 716 insertions(+), 56 deletions(-) create mode 100755 host/lib/transport/gen_vrt.py (limited to 'host/lib/transport') diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py new file mode 100755 index 000000000..918de3ad7 --- /dev/null +++ b/host/lib/transport/gen_vrt.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +""" +The vrt packer/unpacker code generator: + +This script will generate the pack and unpack routines that convert +metatdata into vrt headers and vrt headers into metadata. + +The generated code infers jump tables to speed-up the parsing time. +""" + +TMPL_TEXT = """ +#import time + +######################################################################## +## setup predicates +######################################################################## +#set $sid_p = 0b00001 +#set $cid_p = 0b00010 +#set $tsi_p = 0b00100 +#set $tsf_p = 0b01000 +#set $tlr_p = 0b10000 + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#include +\#include //endianness conversion +\#include + +using namespace uhd; +using namespace uhd::transport; + +void vrt::pack( + const tx_metadata_t &metadata, //input + boost::uint32_t *header_buff, //output + size_t &num_header_words32, //output + size_t num_payload_words32, //input + size_t &num_packet_words32, //output + size_t packet_count //input +){ + boost::uint32_t vrt_hdr_flags; + + boost::uint8_t pred = 0; + if (metadata.has_stream_id) pred |= $hex($sid_p); + if (metadata.has_time_spec) pred |= $hex($tsi_p | $tsf_p); + + switch(pred){ + #for $pred in range(2**5) + case $pred: + #set $num_header_words = 1 + #set $flags = 0 + ########## Stream ID ########## + #if $pred & $sid_p + header_buff[$num_header_words] = htonl(metadata.stream_id); + #set $num_header_words += 1 + #set $flags |= (0x1 << 28); + #end if + ########## Class ID ########## + #if $pred & $cid_p + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + #set $flags |= (0x1 << 27); + #end if + ########## Integer Time ########## + #if $pred & $tsi_p + header_buff[$num_header_words] = htonl(metadata.time_spec.secs); + #set $num_header_words += 1 + #set $flags |= (0x3 << 22); + #end if + ########## Fractional Time ########## + #if $pred & $tsf_p + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + header_buff[$num_header_words] = htonl(metadata.time_spec.ticks); + #set $num_header_words += 1 + #set $flags |= (0x1 << 20); + #end if + ########## Trailer ########## + #if $pred & $tlr_p + #set $flags |= (0x1 << 26); + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if + ########## Variables ########## + num_header_words32 = $num_header_words; + num_packet_words32 = $($num_header_words + $num_trailer_words) + num_payload_words32; + vrt_hdr_flags = $hex($flags); + break; + #end for + } + + //set the burst flags + if (metadata.start_of_burst) vrt_hdr_flags |= $hex(0x1 << 25); + if (metadata.end_of_burst) vrt_hdr_flags |= $hex(0x1 << 24); + + //fill in complete header word + header_buff[0] = htonl(vrt_hdr_flags | + ((packet_count & 0xf) << 16) | + (num_packet_words32 & 0xffff) + ); +} + +void vrt::unpack( + rx_metadata_t &metadata, //output + const boost::uint32_t *header_buff, //input + size_t &num_header_words32, //output + size_t &num_payload_words32, //output + size_t num_packet_words32, //input + size_t &packet_count //output +){ + //clear the metadata + metadata = rx_metadata_t(); + + //extract vrt header + boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]); + size_t packet_words32 = vrt_hdr_word & 0xffff; + packet_count = (vrt_hdr_word >> 16) & 0xf; + + //failure cases + if (packet_words32 == 0 or num_packet_words32 < packet_words32) + throw std::runtime_error("bad vrt header or packet fragment"); + if (vrt_hdr_word & (0x7 << 29)) + throw std::runtime_error("unsupported vrt packet type"); + + boost::uint8_t pred = 0; + if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p); + if(vrt_hdr_word & $hex(0x1 << 27)) pred |= $hex($cid_p); + if(vrt_hdr_word & $hex(0x3 << 22)) pred |= $hex($tsi_p); + if(vrt_hdr_word & $hex(0x3 << 20)) pred |= $hex($tsf_p); + if(vrt_hdr_word & $hex(0x1 << 26)) pred |= $hex($tlr_p); + + switch(pred){ + #for $pred in range(2**5) + case $pred: + #set $set_has_time_spec = False + #set $num_header_words = 1 + ########## Stream ID ########## + #if $pred & $sid_p + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Class ID ########## + #if $pred & $cid_p + #set $num_header_words += 1 + #set $num_header_words += 1 + #end if + ########## Integer Time ########## + #if $pred & $tsi_p + metadata.has_time_spec = true; + #set $set_has_time_spec = True + metadata.time_spec.secs = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Fractional Time ########## + #if $pred & $tsf_p + #if not $set_has_time_spec + metadata.has_time_spec = true; + #set $set_has_time_spec = True + #end if + #set $num_header_words += 1 + metadata.time_spec.ticks = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Trailer ########## + #if $pred & $tlr_p + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if + ########## Variables ########## + num_header_words32 = $num_header_words; + num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words); + break; + #end for + } +} +""" + +from Cheetah import Template +def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs)) + +if __name__ == '__main__': + from Cheetah import Template + print parse_str(TMPL_TEXT, file=__file__) diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index cc46b2381..bebca5db9 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -1,19 +1,9 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// + + + +/*********************************************************************** + * This file was generated by ./gen_vrt.py on Fri Mar 26 15:33:00 2010 + **********************************************************************/ #include #include //endianness conversion @@ -30,26 +20,274 @@ void vrt::pack( size_t &num_packet_words32, //output size_t packet_count //input ){ - boost::uint32_t vrt_hdr_flags = 0; - num_header_words32 = 1; + boost::uint32_t vrt_hdr_flags; - //load the vrt header and flags - if(metadata.has_stream_id){ - vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier - header_buff[num_header_words32++] = htonl(metadata.stream_id); - } + boost::uint8_t pred = 0; + if (metadata.has_stream_id) pred |= 0x1; + if (metadata.has_time_spec) pred |= 0xc; - if(metadata.has_time_spec){ - vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp - header_buff[num_header_words32++] = htonl(metadata.time_spec.secs); - header_buff[num_header_words32++] = 0; //unused part of fractional seconds - header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks); + switch(pred){ + case 0: + num_header_words32 = 1; + num_packet_words32 = 1 + num_payload_words32; + vrt_hdr_flags = 0x0; + break; + case 1: + header_buff[1] = htonl(metadata.stream_id); + num_header_words32 = 2; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0x10000000; + break; + case 2: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x8000000; + break; + case 3: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x18000000; + break; + case 4: + header_buff[1] = htonl(metadata.time_spec.secs); + num_header_words32 = 2; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0xc00000; + break; + case 5: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x10c00000; + break; + case 6: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x8c00000; + break; + case 7: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x18c00000; + break; + case 8: + header_buff[1] = htonl(0); + header_buff[2] = htonl(metadata.time_spec.ticks); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x100000; + break; + case 9: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x10100000; + break; + case 10: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x8100000; + break; + case 11: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x18100000; + break; + case 12: + header_buff[1] = htonl(metadata.time_spec.secs); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0xd00000; + break; + case 13: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x10d00000; + break; + case 14: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x8d00000; + break; + case 15: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + header_buff[5] = htonl(0); + header_buff[6] = htonl(metadata.time_spec.ticks); + num_header_words32 = 7; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0x18d00000; + break; + case 16: + num_header_words32 = 1; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0x4000000; + break; + case 17: + header_buff[1] = htonl(metadata.stream_id); + num_header_words32 = 2; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x14000000; + break; + case 18: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0xc000000; + break; + case 19: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x1c000000; + break; + case 20: + header_buff[1] = htonl(metadata.time_spec.secs); + num_header_words32 = 2; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x4c00000; + break; + case 21: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x14c00000; + break; + case 22: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0xcc00000; + break; + case 23: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x1cc00000; + break; + case 24: + header_buff[1] = htonl(0); + header_buff[2] = htonl(metadata.time_spec.ticks); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x4100000; + break; + case 25: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x14100000; + break; + case 26: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0xc100000; + break; + case 27: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0x1c100000; + break; + case 28: + header_buff[1] = htonl(metadata.time_spec.secs); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x4d00000; + break; + case 29: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x14d00000; + break; + case 30: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0xcd00000; + break; + case 31: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + header_buff[5] = htonl(0); + header_buff[6] = htonl(metadata.time_spec.ticks); + num_header_words32 = 7; + num_packet_words32 = 8 + num_payload_words32; + vrt_hdr_flags = 0x1cd00000; + break; } - vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; - vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0; - - num_packet_words32 = num_header_words32 + num_payload_words32; + //set the burst flags + if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000; + if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000; //fill in complete header word header_buff[0] = htonl(vrt_hdr_flags | @@ -80,30 +318,230 @@ void vrt::unpack( if (vrt_hdr_word & (0x7 << 29)) throw std::runtime_error("unsupported vrt packet type"); - //parse the header flags - num_header_words32 = 1; - - if (vrt_hdr_word & (0x1 << 28)){ //stream id - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[num_header_words32++]); - } - - if (vrt_hdr_word & (0x1 << 27)){ //class id (we dont use) - num_header_words32 += 2; - } - - if (vrt_hdr_word & (0x3 << 22)){ //integer time - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[num_header_words32++]); - } + boost::uint8_t pred = 0; + if(vrt_hdr_word & 0x10000000) pred |= 0x1; + if(vrt_hdr_word & 0x8000000) pred |= 0x2; + if(vrt_hdr_word & 0xc00000) pred |= 0x4; + if(vrt_hdr_word & 0x300000) pred |= 0x8; + if(vrt_hdr_word & 0x4000000) pred |= 0x10; - if (vrt_hdr_word & (0x3 << 20)){ //fractional time - metadata.has_time_spec = true; - num_header_words32++; //unused part of fractional seconds - metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]); + switch(pred){ + case 0: + num_header_words32 = 1; + num_payload_words32 = packet_words32 - 1; + break; + case 1: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 2; + break; + case 2: + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 3: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 4: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 2; + break; + case 5: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 6: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 7: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 8: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 9: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 10: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 11: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 6; + break; + case 12: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 13: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 14: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 6; + break; + case 15: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + metadata.time_spec.ticks = ntohl(header_buff[6]); + num_header_words32 = 7; + num_payload_words32 = packet_words32 - 7; + break; + case 16: + num_header_words32 = 1; + num_payload_words32 = packet_words32 - 2; + break; + case 17: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 3; + break; + case 18: + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 19: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 20: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 3; + break; + case 21: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 22: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 23: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 24: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 25: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 26: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 27: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 7; + break; + case 28: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 29: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 30: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 7; + break; + case 31: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + metadata.time_spec.ticks = ntohl(header_buff[6]); + num_header_words32 = 7; + num_payload_words32 = packet_words32 - 8; + break; } - - size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0; - - num_payload_words32 = packet_words32 - num_header_words32 - num_trailer_words32; } + diff --git a/host/utils/usrp2_recovery.py b/host/utils/usrp2_recovery.py index 48c1121cb..5654e93d3 100755 --- a/host/utils/usrp2_recovery.py +++ b/host/utils/usrp2_recovery.py @@ -1,4 +1,20 @@ #!/usr/bin/env python +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# """ The usrp2 recovery app: -- cgit v1.2.3 From ae02148f12615ab4f8e326dac5cf388ab976ec7f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Mar 2010 17:52:57 -0800 Subject: get interface addresses on windows --- host/lib/CMakeLists.txt | 6 +- host/lib/load_modules.cpp | 2 +- host/lib/transport/if_addrs.cpp | 311 +++++-------------------------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 3 + 4 files changed, 48 insertions(+), 274 deletions(-) (limited to 'host/lib/transport') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a0bfd6d0a..170d1d3bf 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -64,7 +64,7 @@ MESSAGE(STATUS "Configuring module loading...") INCLUDE(CheckIncludeFileCXX) CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) -CHECK_INCLUDE_FILE_CXX(Windows.h HAVE_WINDOWS_H) +CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H) IF(HAVE_DLFCN_H) MESSAGE(STATUS " Module loading supported through dlopen.") @@ -83,10 +83,14 @@ MESSAGE(STATUS "Configuring interface address discovery...") INCLUDE(CheckIncludeFileCXX) CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H) +CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H) IF(HAVE_IFADDRS_H) MESSAGE(STATUS " Interface address discovery supported through getifaddrs.") ADD_DEFINITIONS(-DHAVE_IFADDRS_H) +ELSEIF(HAVE_WINSOCK2_H) + MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.") + ADD_DEFINITIONS(-DHAVE_WINSOCK2_H) ELSE(HAVE_IFADDRS_H) MESSAGE(STATUS " Interface address discovery not supported.") ENDIF(HAVE_IFADDRS_H) diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp index bcdff98a6..77426b898 100644 --- a/host/lib/load_modules.cpp +++ b/host/lib/load_modules.cpp @@ -41,7 +41,7 @@ static void load_module(const std::string &file_name){ } #elif HAVE_WINDOWS_H -#include +#include static void load_module(const std::string &file_name){ if (LoadLibrary(file_name.c_str()) == NULL){ diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp index d3ea448fd..eb0e56b3a 100644 --- a/host/lib/transport/if_addrs.cpp +++ b/host/lib/transport/if_addrs.cpp @@ -36,10 +36,7 @@ static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ } static bool ifaddrs_valid(const struct ifaddrs *ifaddrs){ - return ( - ifaddrs->ifa_addr->sa_family == AF_INET and - sockaddr_to_ip_addr(ifaddrs->ifa_addr) != boost::asio::ip::address_v4::loopback() - ); + return ifaddrs->ifa_addr->sa_family == AF_INET; } std::vector uhd::transport::get_if_addrs(void){ @@ -62,7 +59,44 @@ std::vector uhd::transport::get_if_addrs(void){ /*********************************************************************** * Interface address discovery through windows api (TODO) **********************************************************************/ -//#elif HAVE_XXX_H +#elif HAVE_WINSOCK2_H +#include +#include +#include +#include + +std::vector uhd::transport::get_if_addrs(void){ + std::vector if_addrs; + SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0); + if (sd == SOCKET_ERROR) { + std::cerr << "Failed to get a socket. Error " << WSAGetLastError() << + std::endl; return if_addrs; + } + + INTERFACE_INFO InterfaceList[20]; + unsigned long nBytesReturned; + if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, + sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) { + std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError() << + std::endl; + return if_addrs; + } + + int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); + for (int i = 0; i < nNumInterfaces; ++i) { + boost::uint32_t iiAddress = ntohl(reinterpret_cast(InterfaceList[i].iiAddress).sin_addr.s_addr); + boost::uint32_t iiNetmask = ntohl(reinterpret_cast(InterfaceList[i].iiNetmask).sin_addr.s_addr); + boost::uint32_t iiBroadcastAddress = (iiAddress & iiNetmask) | ~iiNetmask; + + if_addrs_t if_addr; + if_addr.inet = boost::asio::ip::address_v4(iiAddress).to_string(); + if_addr.mask = boost::asio::ip::address_v4(iiNetmask).to_string(); + if_addr.bcast = boost::asio::ip::address_v4(iiBroadcastAddress).to_string(); + if_addrs.push_back(if_addr); + } + + return if_addrs; +} /*********************************************************************** * Interface address discovery not included @@ -74,270 +108,3 @@ std::vector uhd::transport::get_if_addrs(void){ } #endif /* HAVE_IFADDRS_H */ - -//////////////////////////////////////////////////////////////////////// -// How to extract the ip address: unix/windows -// http://www.developerweb.net/forum/showthread.php?t=5085 -//////////////////////////////////////////////////////////////////////// - -/* -#include - -#ifdef WIN32 -# include -# include -# include -#else -# include -# include -# include -# include -# include -# include -# include -#endif - -#include -#include - -typedef unsigned long uint32; - -#if defined(__FreeBSD__) || defined(BSD) || defined(__APPLE__) || defined(__linux__) -# define USE_GETIFADDRS 1 -# include -static uint32 SockAddrToUint32(struct sockaddr * a) -{ - return ((a)&&(a->sa_family == AF_INET)) ? ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0; -} -#endif - -// convert a numeric IP address into its string representation -static void Inet_NtoA(uint32 addr, char * ipbuf) -{ - sprintf(ipbuf, "%li.%li.%li.%li", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF); -} - -// convert a string represenation of an IP address into its numeric equivalent -static uint32 Inet_AtoN(const char * buf) -{ - // net_server inexplicably doesn't have this function; so I'll just fake it - uint32 ret = 0; - int shift = 24; // fill out the MSB first - bool startQuad = true; - while((shift >= 0)&&(*buf)) - { - if (startQuad) - { - unsigned char quad = (unsigned char) atoi(buf); - ret |= (((uint32)quad) << shift); - shift -= 8; - } - startQuad = (*buf == '.'); - buf++; - } - return ret; -} - -static void PrintNetworkInterfaceInfos() -{ -#if defined(USE_GETIFADDRS) - // BSD-style implementation - struct ifaddrs * ifap; - if (getifaddrs(&ifap) == 0) - { - struct ifaddrs * p = ifap; - while(p) - { - uint32 ifaAddr = SockAddrToUint32(p->ifa_addr); - uint32 maskAddr = SockAddrToUint32(p->ifa_netmask); - uint32 dstAddr = SockAddrToUint32(p->ifa_dstaddr); - if (ifaAddr > 0) - { - char ifaAddrStr[32]; Inet_NtoA(ifaAddr, ifaAddrStr); - char maskAddrStr[32]; Inet_NtoA(maskAddr, maskAddrStr); - char dstAddrStr[32]; Inet_NtoA(dstAddr, dstAddrStr); - printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", p->ifa_name, "unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); - } - p = p->ifa_next; - } - freeifaddrs(ifap); - } -#elif defined(WIN32) - // Windows XP style implementation - - // Adapted from example code at http://msdn2.microsoft.com/en-us/library/aa365917.aspx - // Now get Windows' IPv4 addresses table. Once again, we gotta call GetIpAddrTable() - // multiple times in order to deal with potential race conditions properly. - MIB_IPADDRTABLE * ipTable = NULL; - { - ULONG bufLen = 0; - for (int i=0; i<5; i++) - { - DWORD ipRet = GetIpAddrTable(ipTable, &bufLen, false); - if (ipRet == ERROR_INSUFFICIENT_BUFFER) - { - free(ipTable); // in case we had previously allocated it - ipTable = (MIB_IPADDRTABLE *) malloc(bufLen); - } - else if (ipRet == NO_ERROR) break; - else - { - free(ipTable); - ipTable = NULL; - break; - } - } - } - - if (ipTable) - { - // Try to get the Adapters-info table, so we can given useful names to the IP - // addresses we are returning. Gotta call GetAdaptersInfo() up to 5 times to handle - // the potential race condition between the size-query call and the get-data call. - // I love a well-designed API :^P - IP_ADAPTER_INFO * pAdapterInfo = NULL; - { - ULONG bufLen = 0; - for (int i=0; i<5; i++) - { - DWORD apRet = GetAdaptersInfo(pAdapterInfo, &bufLen); - if (apRet == ERROR_BUFFER_OVERFLOW) - { - free(pAdapterInfo); // in case we had previously allocated it - pAdapterInfo = (IP_ADAPTER_INFO *) malloc(bufLen); - } - else if (apRet == ERROR_SUCCESS) break; - else - { - free(pAdapterInfo); - pAdapterInfo = NULL; - break; - } - } - } - - for (DWORD i=0; idwNumEntries; i++) - { - const MIB_IPADDRROW & row = ipTable->table[i]; - - // Now lookup the appropriate adaptor-name in the pAdaptorInfos, if we can find it - const char * name = NULL; - const char * desc = NULL; - if (pAdapterInfo) - { - IP_ADAPTER_INFO * next = pAdapterInfo; - while((next)&&(name==NULL)) - { - IP_ADDR_STRING * ipAddr = &next->IpAddressList; - while(ipAddr) - { - if (Inet_AtoN(ipAddr->IpAddress.String) == ntohl(row.dwAddr)) - { - name = next->AdapterName; - desc = next->Description; - break; - } - ipAddr = ipAddr->Next; - } - next = next->Next; - } - } - char buf[128]; - if (name == NULL) - { - sprintf(buf, "unnamed-%i", i); - name = buf; - } - - uint32 ipAddr = ntohl(row.dwAddr); - uint32 netmask = ntohl(row.dwMask); - uint32 baddr = ipAddr & netmask; - if (row.dwBCastAddr) baddr |= ~netmask; - - char ifaAddrStr[32]; Inet_NtoA(ipAddr, ifaAddrStr); - char maskAddrStr[32]; Inet_NtoA(netmask, maskAddrStr); - char dstAddrStr[32]; Inet_NtoA(baddr, dstAddrStr); - printf(" Found interface: name=[%s] desc=[%s] address=[%s] netmask=[%s] broadcastAddr=[%s]\n", name, desc?desc:"unavailable", ifaAddrStr, maskAddrStr, dstAddrStr); - } - - free(pAdapterInfo); - free(ipTable); - } -#else - // Dunno what we're running on here! -# error "Don't know how to implement PrintNetworkInterfaceInfos() on this OS!" -#endif -} - -int main(int, char **) -{ - PrintNetworkInterfaceInfos(); - return 0; -} -*/ - -//////////////////////////////////////////////////////////////////////// -// How to extract the mac address: linux/windows -// http://old.nabble.com/MAC-Address-td19111197.html -//////////////////////////////////////////////////////////////////////// - -/* -Linux: - -#include -#include -#include -#include -#include -#include -#include - -ifaddrs * ifap = 0; -if(getifaddrs(&ifap) == 0) -{ - ifaddrs * iter = ifap; - while(iter) - { - sockaddr_ll * sal = - reinterpret_cast(iter->ifa_addr); - if(sal->sll_family == AF_PACKET) - { - // get the mac bytes - // copy(sal->sll_addr, - // sal->sll_addr+sal->sll_hallen, - // buffer); - } - iter = iter->ifa_next; - } - freeifaddrs(ifap); -} - -Windows: -#include -#include - -std::vector buf; -DWORD bufLen = 0; -GetAdaptersAddresses(0, 0, 0, 0, &bufLen); -if(bufLen) -{ - buf.resize(bufLen, 0); - IP_ADAPTER_ADDRESSES * ptr = - reinterpret_cast(&buf[0]); - DWORD err = GetAdaptersAddresses(0, 0, 0, ptr, &bufLen); - if(err == NO_ERROR) - { - while(ptr) - { - if(ptr->PhysicalAddressLength) - { - // get the mac bytes - // copy(ptr->PhysicalAddress, - // ptr->PhysicalAddress+ptr->PhysicalAddressLength, - // buffer); - } - ptr = ptr->Next; - } - } -} -*/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index f04ae8d2c..35a4aeb20 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -41,6 +41,9 @@ uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ //if no address was specified, send a broadcast on each interface if (not hint.has_key("addr")){ BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){ + //avoid the loopback device + if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue; + //create a new hint with this broadcast address device_addr_t new_hint = hint; new_hint["addr"] = if_addrs.bcast; -- cgit v1.2.3 From dd41206f2a5127871fc4c9911a748f7f4e3b6c51 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 26 Mar 2010 19:02:32 -0700 Subject: tweak the ifaddrs address discovery --- host/lib/transport/if_addrs.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'host/lib/transport') diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp index eb0e56b3a..5c8c8a176 100644 --- a/host/lib/transport/if_addrs.cpp +++ b/host/lib/transport/if_addrs.cpp @@ -16,6 +16,9 @@ // #include +#include +#include +#include uhd::transport::if_addrs_t::if_addrs_t(void){ /* NOP */ @@ -26,17 +29,11 @@ uhd::transport::if_addrs_t::if_addrs_t(void){ **********************************************************************/ #ifdef HAVE_IFADDRS_H #include -#include static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ - if (addr->sa_family == AF_INET) return boost::asio::ip::address_v4(ntohl( + return boost::asio::ip::address_v4(ntohl( reinterpret_cast(addr)->sin_addr.s_addr )); - return boost::asio::ip::address_v4::any(); -} - -static bool ifaddrs_valid(const struct ifaddrs *ifaddrs){ - return ifaddrs->ifa_addr->sa_family == AF_INET; } std::vector uhd::transport::get_if_addrs(void){ @@ -44,7 +41,12 @@ std::vector uhd::transport::get_if_addrs(void){ struct ifaddrs *ifap; if (getifaddrs(&ifap) == 0){ for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){ - if (not ifaddrs_valid(iter)) continue; + //ensure that the entries are valid + if (iter->ifa_addr->sa_family != AF_INET) continue; + if (iter->ifa_netmask->sa_family != AF_INET) continue; + if (iter->ifa_broadaddr->sa_family != AF_INET) continue; + + //append a new set of interface addresses if_addrs_t if_addr; if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string(); if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string(); @@ -60,10 +62,7 @@ std::vector uhd::transport::get_if_addrs(void){ * Interface address discovery through windows api (TODO) **********************************************************************/ #elif HAVE_WINSOCK2_H -#include -#include #include -#include std::vector uhd::transport::get_if_addrs(void){ std::vector if_addrs; -- cgit v1.2.3