Do I have a threading issue here?
Asked Answered
W

1

7

I have been experimenting with GNU Radio and came across the tunnel.py program. This program allows you to tunnel IP traffic over a wireless radio link using Linux TUN/TAP devices. For the most part it is working however one part of the code is confusing me.

There is a class which implements a 'basic MAC layer'. This class has a callback function which writes a new packet to the TUN device. This function (phy_rx_callback) is called from a separate thread.

The function main_loop does a carrier sense before transmitting a new packet. The thing I don't understand is why it is sensing a receive channel before transmitting on a separate non-overlapping transmit channel.

Both the RX and TX channels are separate frequencies, and our hardware allows full-duplex communication.

SO, my question is with main_loop executing, what are the implications of another thread asynchronously calling the phy_rx_callback function? The problem is I am trying to understand the purpose of the carrier sense loop, I found that commenting that code severely decreases performance. It doesn't make sense to me that you would monitor a receive channel before using a transmit channel, essentially turning it into half-duplex. Then I don't see the purpose of using two frequencies, one for transmit and one for receive. I began to wonder if there was a strange threading issue at work here.

A single instance of the cs_mac class is created initially. A 'pointer' to the rx_callback function is passed down a few levels to the thread class which actually calls it. Here is the cs_mac class:

class cs_mac(object):
    def __init__(self, tun_fd, verbose=False):
        self.tun_fd = tun_fd       # file descriptor for TUN/TAP interface
        self.verbose = verbose
        self.tb = None             # top block (access to PHY)

    def set_top_block(self, tb):
        self.tb = tb

    def phy_rx_callback(self, ok, payload):
        if self.verbose:
            print "Rx: ok = %r  len(payload) = %4d" % (ok, len(payload))
        if ok:
            os.write(self.tun_fd, payload)

    def main_loop(self):
        min_delay = 0.001               # seconds
        while 1:
            payload = os.read(self.tun_fd, 10*1024)
            if not payload:
                self.tb.send_pkt(eof=True)
                break
            if self.verbose:
                print "Tx: len(payload) = %4d" % (len(payload),)
            delay = min_delay
            while self.tb.carrier_sensed():
                sys.stderr.write('B')
                time.sleep(delay)
                if delay < 0.050:
                    delay = delay * 2       # exponential back-off
            self.tb.send_pkt(payload)

Ok, so using ctypes.CDLL('libc.so.6').syscall(186)), which calls gettid I discovered that the thread calling the rx_callback function has the same PID, but a different TID.

The question becomes, what are the implications of having a separate thread call a function from an object in the main thread (while that thread is constantly looping)?

Whallon answered 13/4, 2011 at 14:21 Comment(1)
Can't say I know much about GNU Radio but here's my 2 cents. You shouldn't have problems putting the TX and RX in separate threads as long as they use separate resources on the GNU Radio side -- both software- and hardware-wise. You say that they use separate channels so it sounds like they may be separate. On the other hand, they are using the same antenna, so can you really transmit and receive at the same time?Pulsar
B
0

The function main_loop does a carrier sense before transmitting a new packet. The thing I don't understand is why it is sensing a receive channel before transmitting on a separate non-overlapping transmit channel.

The CSMA/CA is intended to be used with half-duplex systems, where all nodes use the same frequency to TX and RX. So you are right, there is no point in sensing the RX channel if you are transmitting in a different one.

carrier_sensed() is called in the receive_path.py file so it should run in the RX thread. In my code I comment out the lines sys.stderr.write('B') and time.sleep(delay) and this does not seem to affect performance. It might be different in my case since I use an XCVR daughter board which is half-duplex.

Bloodshed answered 21/4, 2011 at 3:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.