Recently, I have been working on integrating Click Modular Router to work with both WiFi cards and USRPs to facilitate the development of cognitive radio testbeds. I am using GNURadio to control N210 USRPs. I found that developing routing hops to be interesting and worth sharing as it requires the USRP to simultaneously send and receive. This requires the transmission and reception to be on separated frequencies.
For transmission, first a client socket must be created in the click configuration code.
Socket(TCP, localhost, 4002, Client true)
Then, I used a thread to constantly listens on that socket and transmits the data once a new packet is received. This allows for the separation of tasks and good visibility of the transmission code. I noticed that there is a trend to include the transmission code within the main function which degrades the code readability. The thread takes as a parameter the top_block describing the data path on the USRP.
class tx_th (threading.Thread): def __init__(self,tb): threading.Thread.__init__(self) self.tb = tb self.tx_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.tx_soc.bind(('',4002)) self.tx_soc.listen(1) self.tx_soc_client,addrr = self.tx_soc.accept() self.pktno = 0 self.pkt_size = 1500 def run(self): print "Thread Started ..." while True: try: data = self.tx_soc_client.recv(1024) if data: control_flag = struct.unpack('i', data[0:4]) if control_flag == 0: target_tx_freq = struct.unpack('i', data[4:8]) self.tb.source.u.set_center_freq(target_tx_freq, 0) else: data_to_be_sent = data[1:] payload = struct.pack('!H', self.pktno & 0xffff) + data_to_be_sent self.tb.txpath.send_pkt(payload, False) self.pktno += 1 sys.stderr.write('.') except: print traceback.format_exc() t= 1As for the reception, a server socket is created in the Click configuration file.
Socket(TCP, localhost, 4001, Client false)And in the USRP control code, the rx_callback method is modified to be:
def rx_callback(ok, payload): global n_rcvd, n_right, s (pktno,) = struct.unpack('!H', payload[0:2]) data_recv = payload[2:] if s is None: print "Data Socket Recv None" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1",4001)) s.send(data_recv) else: s.send(data_recv)The assumption here is that each packet is annotated with its packet number (for debugging purposes).