mirror of https://gerrit.osmocom.org/libusrp
456 lines
14 KiB
C++
456 lines
14 KiB
C++
/* -*- c++ -*- */
|
|
/*
|
|
* Copyright 2007 Free Software Foundation, Inc.
|
|
*
|
|
* This file is part of GNU Radio
|
|
*
|
|
* GNU Radio 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, or (at your option)
|
|
* any later version.
|
|
*
|
|
* GNU Radio 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, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <qa_inband_usrp_server.h>
|
|
#include <cppunit/TestAssert.h>
|
|
#include <stdio.h>
|
|
#include <usrp_server.h>
|
|
#include <mb_mblock.h>
|
|
#include <mb_runtime.h>
|
|
#include <mb_protocol_class.h>
|
|
#include <mb_class_registry.h>
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
|
|
static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
|
|
static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
|
|
static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
|
|
static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
|
|
static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
|
|
static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
|
|
static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
|
|
static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
|
|
static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
|
|
static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
|
|
static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
|
|
static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
|
|
static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
|
|
class qa_alloc_top : public mb_mblock
|
|
{
|
|
mb_port_sptr d_tx;
|
|
mb_port_sptr d_rx;
|
|
mb_port_sptr d_cs;
|
|
|
|
long d_nmsgs_to_recv;
|
|
long d_nrecvd;
|
|
|
|
long d_max_capacity;
|
|
long d_ntx_chan, d_nrx_chan;
|
|
|
|
long d_nstatus;
|
|
long d_nstatus_to_recv;
|
|
|
|
public:
|
|
qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
|
~qa_alloc_top();
|
|
void initial_transition();
|
|
void handle_message(mb_message_sptr msg);
|
|
|
|
protected:
|
|
void check_message(mb_message_sptr msg);
|
|
void run_tests();
|
|
};
|
|
|
|
qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
|
: mb_mblock(runtime, instance_name, user_arg)
|
|
{
|
|
d_nrecvd=0;
|
|
d_nmsgs_to_recv = 7;
|
|
d_nstatus=0;
|
|
d_nstatus_to_recv = 3;
|
|
|
|
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
|
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
|
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
|
|
|
// Test the TX side
|
|
define_component("server", "usrp_server", PMT_F);
|
|
connect("self", "tx0", "server", "tx0");
|
|
connect("self", "rx0", "server", "rx0");
|
|
connect("self", "cs", "server", "cs");
|
|
|
|
}
|
|
|
|
qa_alloc_top::~qa_alloc_top(){}
|
|
|
|
void
|
|
qa_alloc_top::initial_transition()
|
|
{
|
|
// Retrieve information about the USRP, then run tests
|
|
d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
|
|
d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
|
|
d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
|
|
}
|
|
|
|
void
|
|
qa_alloc_top::run_tests()
|
|
{
|
|
std::cout << "[qa_alloc_top] Starting tests...\n";
|
|
// should be able to allocate 1 byte
|
|
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
|
|
// should not be able to allocate max capacity after 100 bytes were allocated
|
|
d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
|
|
|
|
// keep allocating a little more until all of the channels are used and test the error response
|
|
// we start at 1 since we've already allocated 1 channel
|
|
for(int i=1; i < d_ntx_chan; i++) {
|
|
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
d_nmsgs_to_recv++;
|
|
}
|
|
d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
|
|
|
|
// test out the same on the RX side
|
|
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
|
|
|
|
for(int i=1; i < d_nrx_chan; i++) {
|
|
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
d_nmsgs_to_recv++;
|
|
}
|
|
d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
|
|
|
|
// when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes allocated
|
|
d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
|
|
}
|
|
|
|
void
|
|
qa_alloc_top::handle_message(mb_message_sptr msg)
|
|
{
|
|
pmt_t data = msg->data();
|
|
|
|
if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
|
|
|| pmt_eq(msg->port_id(), d_rx->port_symbol()))
|
|
&& pmt_eq(msg->signal(), s_response_allocate_channel))
|
|
check_message(msg);
|
|
|
|
if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
|
|
|
|
if(pmt_eq(msg->signal(), s_response_max_capacity)) {
|
|
d_max_capacity = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
|
|
d_ntx_chan = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
|
|
d_nrx_chan = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
|
|
check_message(msg);
|
|
}
|
|
|
|
d_nstatus++;
|
|
|
|
if(d_nstatus==d_nstatus_to_recv)
|
|
run_tests();
|
|
}
|
|
}
|
|
|
|
void
|
|
qa_alloc_top::check_message(mb_message_sptr msg)
|
|
{
|
|
pmt_t data = msg->data();
|
|
|
|
pmt_t expected_result = pmt_nth(0, data);
|
|
pmt_t result = pmt_nth(1, data);
|
|
|
|
d_nrecvd++;
|
|
|
|
|
|
if(!pmt_eqv(expected_result, result)) {
|
|
std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
|
|
shutdown_all(PMT_F);
|
|
} else {
|
|
std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
|
|
}
|
|
|
|
if(d_nrecvd == d_nmsgs_to_recv)
|
|
shutdown_all(PMT_T);
|
|
}
|
|
|
|
REGISTER_MBLOCK_CLASS(qa_alloc_top);
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
|
|
class qa_dealloc_top : public mb_mblock
|
|
{
|
|
mb_port_sptr d_tx;
|
|
mb_port_sptr d_rx;
|
|
mb_port_sptr d_cs;
|
|
|
|
long d_max_capacity;
|
|
long d_ntx_chan, d_nrx_chan;
|
|
|
|
long d_nstatus;
|
|
long d_nstatus_to_recv;
|
|
|
|
long d_nalloc_to_recv;
|
|
long d_nalloc_recvd;
|
|
|
|
long d_ndealloc_to_recv;
|
|
long d_ndealloc_recvd;
|
|
|
|
std::vector<long> d_tx_chans;
|
|
std::vector<long> d_rx_chans;
|
|
|
|
public:
|
|
qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
|
~qa_dealloc_top();
|
|
void initial_transition();
|
|
void handle_message(mb_message_sptr msg);
|
|
|
|
protected:
|
|
void check_allocation(mb_message_sptr msg);
|
|
void check_deallocation(mb_message_sptr msg);
|
|
void allocate_max();
|
|
void deallocate_all();
|
|
};
|
|
|
|
qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
|
: mb_mblock(runtime, instance_name, user_arg)
|
|
{
|
|
d_ndealloc_recvd=0;
|
|
d_ndealloc_to_recv = 0;
|
|
d_nalloc_recvd=0;
|
|
d_nalloc_to_recv = 0;
|
|
d_nstatus=0;
|
|
d_nstatus_to_recv = 3;
|
|
|
|
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
|
|
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
|
|
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
|
|
|
|
// Test the TX side
|
|
define_component("server", "usrp_server", PMT_F);
|
|
connect("self", "tx0", "server", "tx0");
|
|
connect("self", "rx0", "server", "rx0");
|
|
connect("self", "cs", "server", "cs");
|
|
}
|
|
|
|
qa_dealloc_top::~qa_dealloc_top(){}
|
|
|
|
void
|
|
qa_dealloc_top::initial_transition()
|
|
{
|
|
// Retrieve information about the USRP, then run tests
|
|
d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
|
|
d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
|
|
d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
|
|
}
|
|
|
|
void
|
|
qa_dealloc_top::allocate_max()
|
|
{
|
|
std::cout << "[qa_dealloc_top] Max allocating...\n";
|
|
|
|
// Keep allocating until we hit the maximum number of channels
|
|
for(int i=0; i < d_ntx_chan; i++) {
|
|
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
d_nalloc_to_recv++;
|
|
}
|
|
for(int i=0; i < d_nrx_chan; i++) {
|
|
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
|
|
d_nalloc_to_recv++;
|
|
}
|
|
}
|
|
|
|
void
|
|
qa_dealloc_top::deallocate_all() {
|
|
|
|
// Deallocate all of the channels that were allocated from allocate_max()
|
|
for(int i=0; i < (int)d_tx_chans.size(); i++) {
|
|
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_tx_chans[i])));
|
|
d_ndealloc_to_recv++;
|
|
}
|
|
for(int i=0; i < (int)d_rx_chans.size(); i++) {
|
|
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_rx_chans[i])));
|
|
d_ndealloc_to_recv++;
|
|
}
|
|
|
|
// Should get permission denied errors trying to re-dealloc the channels, as we no
|
|
// longer have permission to them after deallocating
|
|
for(int i=0; i < (int)d_tx_chans.size(); i++) {
|
|
d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_tx_chans[i])));
|
|
d_ndealloc_to_recv++;
|
|
}
|
|
for(int i=0; i < (int)d_rx_chans.size(); i++) {
|
|
d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_rx_chans[i])));
|
|
d_ndealloc_to_recv++;
|
|
}
|
|
|
|
// Try to deallocate a channel that doesn't exist on both sides, the last element in the vectors
|
|
// is the highest channel number, so we take that plus 1
|
|
d_ndealloc_to_recv+=2;
|
|
d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
|
|
d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
|
|
|
|
|
|
// The used capacity should be back to 0 now that we've deallocated everything
|
|
d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(0)));
|
|
}
|
|
|
|
void
|
|
qa_dealloc_top::handle_message(mb_message_sptr msg)
|
|
{
|
|
pmt_t data = msg->data();
|
|
if (pmt_eq(msg->port_id(), d_tx->port_symbol())
|
|
|| pmt_eq(msg->port_id(), d_rx->port_symbol())) {
|
|
|
|
if(pmt_eq(msg->signal(), s_response_allocate_channel)) {
|
|
check_allocation(msg);
|
|
}
|
|
|
|
if(pmt_eq(msg->signal(), s_response_deallocate_channel)){
|
|
check_deallocation(msg);
|
|
}
|
|
}
|
|
|
|
if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
|
|
|
|
if(pmt_eq(msg->signal(), s_response_max_capacity)) {
|
|
d_max_capacity = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_dealloc_top] USRP has max capacity of " << d_max_capacity << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
|
|
d_ntx_chan = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_dealloc_top] USRP tx channels: " << d_ntx_chan << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
|
|
d_nrx_chan = pmt_to_long(pmt_nth(1, data));
|
|
std::cout << "[qa_dealloc_top] USRP rx channels: " << d_nrx_chan << "\n";
|
|
}
|
|
else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
|
|
// the final command is a capacity check which should be 0, then we shutdown
|
|
pmt_t expected_result = pmt_nth(0, data);
|
|
pmt_t result = pmt_nth(1, data);
|
|
|
|
if(pmt_eqv(expected_result, result))
|
|
shutdown_all(PMT_T);
|
|
else
|
|
shutdown_all(PMT_F);
|
|
}
|
|
|
|
d_nstatus++;
|
|
|
|
if(d_nstatus==d_nstatus_to_recv)
|
|
allocate_max();
|
|
}
|
|
}
|
|
|
|
void
|
|
qa_dealloc_top::check_deallocation(mb_message_sptr msg)
|
|
{
|
|
pmt_t data = msg->data();
|
|
|
|
pmt_t expected_result = pmt_nth(0, data);
|
|
pmt_t result = pmt_nth(1, data);
|
|
|
|
d_ndealloc_recvd++;
|
|
|
|
if(!pmt_eqv(expected_result, result)) {
|
|
std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
|
|
shutdown_all(PMT_F);
|
|
} else {
|
|
std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
|
|
}
|
|
}
|
|
|
|
void
|
|
qa_dealloc_top::check_allocation(mb_message_sptr msg)
|
|
{
|
|
pmt_t data = msg->data();
|
|
|
|
pmt_t invocation_handle = pmt_nth(0, data);
|
|
pmt_t status = pmt_nth(1, data);
|
|
pmt_t channel = pmt_nth(2, data);
|
|
|
|
d_nalloc_recvd++;
|
|
|
|
if(pmt_eqv(status, PMT_F)) {
|
|
std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
|
|
shutdown_all(PMT_F);
|
|
} else {
|
|
// store all of the allocate channel numbers
|
|
if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
|
|
d_tx_chans.push_back(pmt_to_long(channel));
|
|
if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
|
|
d_rx_chans.push_back(pmt_to_long(channel));
|
|
}
|
|
|
|
if(d_nalloc_recvd == d_nalloc_to_recv) {
|
|
|
|
std::cout << "[qa_dealloc_top] Allocated TX channels: ";
|
|
for(int i=0; i < (int)d_tx_chans.size(); i++)
|
|
std::cout << d_tx_chans[i] << " ";
|
|
|
|
std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
|
|
for(int i=0; i < (int)d_rx_chans.size(); i++)
|
|
std::cout << d_rx_chans[i] << " ";
|
|
std::cout << "\n";
|
|
|
|
deallocate_all(); // once we've allocated all of our channels, try to dealloc them
|
|
}
|
|
}
|
|
|
|
REGISTER_MBLOCK_CLASS(qa_dealloc_top);
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
|
|
void
|
|
qa_inband_usrp_server::test_chan_allocation()
|
|
{
|
|
mb_runtime_sptr rt = mb_make_runtime();
|
|
pmt_t result = PMT_T;
|
|
|
|
rt->run("top", "qa_alloc_top", PMT_F, &result);
|
|
|
|
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
|
|
}
|
|
|
|
void
|
|
qa_inband_usrp_server::test_chan_deallocation()
|
|
{
|
|
mb_runtime_sptr rt = mb_make_runtime();
|
|
pmt_t result = PMT_T;
|
|
|
|
rt->run("top", "qa_dealloc_top", PMT_F, &result);
|
|
|
|
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
|
|
}
|
|
|
|
void
|
|
qa_inband_usrp_server::test_fragmentation()
|
|
{
|
|
|
|
}
|