Problem with carrier sense in USRP

Hi,
I am testing the carrier sense mechanism on USRP based on code from
benchmark_tx.py and tunnel.py. My scenario is to receive packets from
two
distinctive nodes simultaneously at the third node. I am prefixing the
payload with sender node name to identify the sender.

When I am trying to send the packets from two nodes simultaneously, the
packets are still colliding, though I have incorporated carrier sense
mechanism in to my code. Please help me in this respect and if possible
suggest me a solution.

I think, packets are being sent by the lower level C++ processing blocks
and
send_pkt() just enqueues the packets. So rather than holding sending of
packet, this code is just holding the packet from getting enqueued in
message queue. Which is not really the holding of packet till carrier is
free. Once packets are in message queue, they are transmitted
irrespective
of carrier availability. So there is still possibility of packet
collision.
Am I correct in my understanding of this real-time scenario?

Attached following is the code of sender application. Receiving
application
is more or less similar to benchmark_rx.py with ability to identify the
packets.

Tx_carrier_sense.py

class my_top_block(gr.top_block):
def init(self, modulator, demodulator, rx_callback, options):
gr.top_block.init(self)
self.txpath = transmit_path(modulator, options)
self.rxpath = receive_path(demodulator, rx_callback, options)
self.connect(self.txpath)
self.connect(self.rxpath)

/////////////////////////////////////////////////////////////////////////////

main

/////////////////////////////////////////////////////////////////////////////

def main():

def send_pkt(payload='', eof=False):
    return tb.txpath.send_pkt(payload, eof)

if name == ‘main’:
try:
main()
except KeyboardInterrupt:
pass
def rx_callback(ok, payload):
print “ok = %r” % (ok)

def carrier_sensed():
    """  Return True if the receive path thinks there's carrier """

return tb.rxpath.carrier_sensed()

demods = modulation_utils.type_1_demods()
mods = modulation_utils.type_1_mods()

parser = OptionParser(option_class=eng_option,

conflict_handler=“resolve”)
expert_grp = parser.add_option_group(“Expert”)

parser.add_option("-m", "--modulation", type="choice",

choices=mods.keys(),
default=‘gmsk’,
help=“Select modulation from: %s
[default=%%default]”
% (', '.join(mods.keys()),))

parser.add_option("-s", "--size", type="eng_float", default=1500,
                  help="set packet size [default=%default]")
parser.add_option("-M", "--megabytes", type="eng_float", 

default=1.0,
help=“set megabytes to transmit
[default=%default]”)
parser.add_option(“”,“–discontinuous”, action=“store_true”,
default=False,
help=“enable discontinous transmission (bursts of
5
packets)”)
parser.add_option(“”,“–from-file”, default=None,
help=“use file for packet contents”)

receive_path.add_options(parser, expert_grp)
transmit_path.add_options(parser, expert_grp)

for mod in mods.values():
    mod.add_options(expert_grp)

fusb_options.add_options(expert_grp)
(options, args) = parser.parse_args ()

if len(args) != 0:
    parser.print_help()
    sys.exit(1)

if options.tx_freq is None:
    sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
    parser.print_help(sys.stderr)
    sys.exit(1)

if options.from_file is not None:
    source_file = open(options.from_file, 'r')

if name == ‘main’:
try:
main()
except KeyboardInterrupt:
pass
# build the graph
tb = my_top_block(mods[options.modulation],
demods[options.modulation],
rx_callback, options)

r = gr.enable_realtime_scheduling()
if r != gr.RT_OK:
    print "Warning: failed to enable realtime scheduling"

tb.start()                       # start flow graph

# generate and send packets
nbytes = int(1e6 * options.megabytes)
n = 0
pktno = 0
pkt_size = int(options.size)

min_delay = 0.0001
while n < nbytes:
    if options.from_file is None:
  data = "C-node" + (pkt_size - 8) * chr(pktno & 0xff)
    else:
        data = source_file.read(pkt_size - 2)
        if data == '':
            break;

    payload = struct.pack('!H', pktno & 0xffff) + data
    delay = min_delay

while carrier_sensed():
print “sensed”
time.sleep(delay)
if delay < 0.050:
delay = delay * 2 # exponential back-off

    send_pkt(payload)
    n += len(payload)
    sys.stderr.write('.')
    if options.discontinuous and pktno % 5 == 4:
        time.sleep(0.3) # default = 1
    pktno += 1

delay = min_delay
while carrier_sensed():

time.sleep(delay)
if delay < 0.050:
delay = delay * 2 # exponential back-off

send_pkt(eof=True)

tb.wait()                       # wait for it to finish

if name == ‘main’:
try:
main()
except KeyboardInterrupt:
pass

View this message in context:
http://www.nabble.com/problem-with-carrier-sense-in-USRP-tp20492283p20492283.html
Sent from the GnuRadio mailing list archive at Nabble.com.

Collisions are still very likely in a software-defined radio
architecture if you implement the carrier sense mechanism on the host
(your machine running GNU Radio). If you think about it, carrier sense
needs to check if the medium is idle, if it is, it then sends.
If you think about the USRP and GNU Radio, the information it uses to
check if the medium is idle is as old as it takes to get from the RF
frontend on the USRP to GNU Radio. That time to get all the way up to
your processing blocks is likely over 1 or 2ms. Therefore, when it says
“oh, the channel is idle!” What’s is really saying is: “oh, the channel
was idle 1 or 2ms ago.” That essentially breaks carrier sense.

To make matters even worse, when it thinks its captured the channel by
choosing to transmit, the transmission takes another 1ms to actually get
from the carrier sense decision mechanism to the USRP. So, your carrier
sense is roughly 2ms off, and anything can happen during that period.
This is referred to as a “carrier sense blind-spot.” The larger the
blind-spot, the more poor carrier sense is going to perform.

We have done work here on getting around these high latency issues by
implementing a split-functionality architecture to core MAC functions on
GNU Radio and the USRP. The idea is: implement part of the function on
the USRP, but leave the control completely at the host. So for example,
we modified GNU Radio and the USRP where GNU Radio sets the carrier
sense threshold on the USRP, and the USRP performs the carrier sense.
We’ve measured the blind spot in GNU Radio to be ~2ms, and with our
split-functionality it is ~1.5us. Major difference.

Our code release is pending on functionality in GNU Radio, and includes
many other optimizations for MAC functionality in software-defined
radios.

  • George

hi,
i also try to search for send_pkt() function…could any one tell me
where
to find this function in GNU radio package? i think it is on C++ code
isn’t
it?but when i search in the CLASS list on
http://gnuradio.org/trac/browser/gnuradio/trunk i couldn’t find any…or
maybe i miss it? please help me… thank you.

adib sairi

Hi,
I am testing the carrier sense mechanism on USRP based on code from
benchmark_tx.py and tunnel.py. My scenario is to receive packets from
two
distinctive nodes simultaneously at the third node. I am prefixing the
payload with sender node name to identify the sender.

When I am trying to send the packets from two nodes simultaneously, the
packets are still colliding, though I have incorporated carrier sense
mechanism in to my code. Please help me in this respect and if possible
suggest me a solution.

I think, packets are being sent by the lower level C++ processing blocks
and
send_pkt() just enqueues the packets. So rather than holding sending of
packet, this code is just holding the packet from getting enqueued in
message queue. Which is not really the holding of packet till carrier is
free. Once packets are in message queue, they are transmitted
irrespective
of carrier availability. So there is still possibility of packet
collision.
Am I correct in my understanding of this real-time scenario?


View this message in context:
http://www.nabble.com/problem-with-carrier-sense-in-USRP-tp20492283p21247975.html
Sent from the GnuRadio mailing list archive at Nabble.com.