3 * Copyright 2007 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <qa_inband_usrp_server.h>
27 #include <cppunit/TestAssert.h>
29 #include <usrp_server.h>
30 #include <mb_mblock.h>
31 #include <mb_runtime.h>
32 #include <mb_protocol_class.h>
33 #include <mb_class_registry.h>
37 static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
38 static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
39 static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
40 static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
41 static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
42 static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
43 static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
44 static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
45 static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
46 static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
47 static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
48 static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
49 static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
50 static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
53 // ----------------------------------------------------------------------------------------------
55 class qa_alloc_top : public mb_mblock
65 long d_ntx_chan, d_nrx_chan;
68 long d_nstatus_to_recv;
71 qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
73 void initial_transition();
74 void handle_message(mb_message_sptr msg);
77 void check_message(mb_message_sptr msg);
81 qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
82 : mb_mblock(runtime, instance_name, user_arg)
87 d_nstatus_to_recv = 3;
89 d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
90 d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
91 d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
94 define_component("server", "usrp_server", PMT_F);
95 connect("self", "tx0", "server", "tx0");
96 connect("self", "rx0", "server", "rx0");
97 connect("self", "cs", "server", "cs");
101 qa_alloc_top::~qa_alloc_top(){}
104 qa_alloc_top::initial_transition()
106 // Retrieve information about the USRP, then run tests
107 d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
108 d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
109 d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
113 qa_alloc_top::run_tests()
115 std::cout << "[qa_alloc_top] Starting tests...\n";
116 // should be able to allocate 1 byte
117 d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
119 // should not be able to allocate max capacity after 100 bytes were allocated
120 d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
122 // keep allocating a little more until all of the channels are used and test the error response
123 // we start at 1 since we've already allocated 1 channel
124 for(int i=1; i < d_ntx_chan; i++) {
125 d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
128 d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
130 // test out the same on the RX side
131 d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
132 d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
134 for(int i=1; i < d_nrx_chan; i++) {
135 d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
138 d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
140 // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes allocated
141 d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
145 qa_alloc_top::handle_message(mb_message_sptr msg)
147 pmt_t data = msg->data();
149 if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
150 || pmt_eq(msg->port_id(), d_rx->port_symbol()))
151 && pmt_eq(msg->signal(), s_response_allocate_channel))
154 if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
156 if(pmt_eq(msg->signal(), s_response_max_capacity)) {
157 d_max_capacity = pmt_to_long(pmt_nth(1, data));
158 std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n";
160 else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
161 d_ntx_chan = pmt_to_long(pmt_nth(1, data));
162 std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n";
164 else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
165 d_nrx_chan = pmt_to_long(pmt_nth(1, data));
166 std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n";
168 else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
174 if(d_nstatus==d_nstatus_to_recv)
180 qa_alloc_top::check_message(mb_message_sptr msg)
182 pmt_t data = msg->data();
184 pmt_t expected_result = pmt_nth(0, data);
185 pmt_t result = pmt_nth(1, data);
190 if(!pmt_eqv(expected_result, result)) {
191 std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
194 std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
197 if(d_nrecvd == d_nmsgs_to_recv)
201 REGISTER_MBLOCK_CLASS(qa_alloc_top);
203 // ----------------------------------------------------------------------------------------------
205 class qa_dealloc_top : public mb_mblock
212 long d_ntx_chan, d_nrx_chan;
215 long d_nstatus_to_recv;
217 long d_nalloc_to_recv;
220 long d_ndealloc_to_recv;
221 long d_ndealloc_recvd;
223 std::vector<long> d_tx_chans;
224 std::vector<long> d_rx_chans;
227 qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
229 void initial_transition();
230 void handle_message(mb_message_sptr msg);
233 void check_allocation(mb_message_sptr msg);
234 void check_deallocation(mb_message_sptr msg);
236 void deallocate_all();
239 qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
240 : mb_mblock(runtime, instance_name, user_arg)
243 d_ndealloc_to_recv = 0;
245 d_nalloc_to_recv = 0;
247 d_nstatus_to_recv = 3;
249 d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
250 d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
251 d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
254 define_component("server", "usrp_server", PMT_F);
255 connect("self", "tx0", "server", "tx0");
256 connect("self", "rx0", "server", "rx0");
257 connect("self", "cs", "server", "cs");
260 qa_dealloc_top::~qa_dealloc_top(){}
263 qa_dealloc_top::initial_transition()
265 // Retrieve information about the USRP, then run tests
266 d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
267 d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
268 d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
272 qa_dealloc_top::allocate_max()
274 std::cout << "[qa_dealloc_top] Max allocating...\n";
276 // Keep allocating until we hit the maximum number of channels
277 for(int i=0; i < d_ntx_chan; i++) {
278 d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
281 for(int i=0; i < d_nrx_chan; i++) {
282 d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
288 qa_dealloc_top::deallocate_all() {
290 // Deallocate all of the channels that were allocated from allocate_max()
291 for(int i=0; i < (int)d_tx_chans.size(); i++) {
292 d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_tx_chans[i])));
293 d_ndealloc_to_recv++;
295 for(int i=0; i < (int)d_rx_chans.size(); i++) {
296 d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_rx_chans[i])));
297 d_ndealloc_to_recv++;
300 // Should get permission denied errors trying to re-dealloc the channels, as we no
301 // longer have permission to them after deallocating
302 for(int i=0; i < (int)d_tx_chans.size(); i++) {
303 d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_tx_chans[i])));
304 d_ndealloc_to_recv++;
306 for(int i=0; i < (int)d_rx_chans.size(); i++) {
307 d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_rx_chans[i])));
308 d_ndealloc_to_recv++;
311 // Try to deallocate a channel that doesn't exist on both sides, the last element in the vectors
312 // is the highest channel number, so we take that plus 1
313 d_ndealloc_to_recv+=2;
314 d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
315 d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
318 // The used capacity should be back to 0 now that we've deallocated everything
319 d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(0)));
323 qa_dealloc_top::handle_message(mb_message_sptr msg)
325 pmt_t data = msg->data();
326 if (pmt_eq(msg->port_id(), d_tx->port_symbol())
327 || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
329 if(pmt_eq(msg->signal(), s_response_allocate_channel)) {
330 check_allocation(msg);
333 if(pmt_eq(msg->signal(), s_response_deallocate_channel)){
334 check_deallocation(msg);
338 if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
340 if(pmt_eq(msg->signal(), s_response_max_capacity)) {
341 d_max_capacity = pmt_to_long(pmt_nth(1, data));
342 std::cout << "[qa_dealloc_top] USRP has max capacity of " << d_max_capacity << "\n";
344 else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
345 d_ntx_chan = pmt_to_long(pmt_nth(1, data));
346 std::cout << "[qa_dealloc_top] USRP tx channels: " << d_ntx_chan << "\n";
348 else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
349 d_nrx_chan = pmt_to_long(pmt_nth(1, data));
350 std::cout << "[qa_dealloc_top] USRP rx channels: " << d_nrx_chan << "\n";
352 else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
353 // the final command is a capacity check which should be 0, then we shutdown
354 pmt_t expected_result = pmt_nth(0, data);
355 pmt_t result = pmt_nth(1, data);
357 if(pmt_eqv(expected_result, result))
365 if(d_nstatus==d_nstatus_to_recv)
371 qa_dealloc_top::check_deallocation(mb_message_sptr msg)
373 pmt_t data = msg->data();
375 pmt_t expected_result = pmt_nth(0, data);
376 pmt_t result = pmt_nth(1, data);
380 if(!pmt_eqv(expected_result, result)) {
381 std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
384 std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
389 qa_dealloc_top::check_allocation(mb_message_sptr msg)
391 pmt_t data = msg->data();
393 pmt_t invocation_handle = pmt_nth(0, data);
394 pmt_t status = pmt_nth(1, data);
395 pmt_t channel = pmt_nth(2, data);
399 if(pmt_eqv(status, PMT_F)) {
400 std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
403 // store all of the allocate channel numbers
404 if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
405 d_tx_chans.push_back(pmt_to_long(channel));
406 if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
407 d_rx_chans.push_back(pmt_to_long(channel));
410 if(d_nalloc_recvd == d_nalloc_to_recv) {
412 std::cout << "[qa_dealloc_top] Allocated TX channels: ";
413 for(int i=0; i < (int)d_tx_chans.size(); i++)
414 std::cout << d_tx_chans[i] << " ";
416 std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
417 for(int i=0; i < (int)d_rx_chans.size(); i++)
418 std::cout << d_rx_chans[i] << " ";
421 deallocate_all(); // once we've allocated all of our channels, try to dealloc them
425 REGISTER_MBLOCK_CLASS(qa_dealloc_top);
427 // ----------------------------------------------------------------------------------------------
430 qa_inband_usrp_server::test_chan_allocation()
432 mb_runtime_sptr rt = mb_make_runtime();
433 pmt_t result = PMT_T;
435 rt->run("top", "qa_alloc_top", PMT_F, &result);
437 CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
441 qa_inband_usrp_server::test_chan_deallocation()
443 mb_runtime_sptr rt = mb_make_runtime();
444 pmt_t result = PMT_T;
446 rt->run("top", "qa_dealloc_top", PMT_F, &result);
448 CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
452 qa_inband_usrp_server::test_fragmentation()