Data transmission

Receiving and sending data can be done through NDP subsystem.

Note

Ensure the firmware datapath isn’t blocked (e.g. MACs are enabled)

# 2.A Data transmission on specific queue
#########################################

# NFB data plane representer
ndp = dev.ndp
rxq = ndp.rx[0]
txq = ndp.tx[0]

# start the queue; this step is optional
# for loopback test purposes helps to avoid discarding on RxQ
rxq.start()
txq.start()

# Raw frames are represented by bytes
pkt = bytes([0] * 64)
hdr = bytes([0] * 16)


# Transmitting frames
# -------------------

# send 64B frame
txq.send(pkt)
# write two 64B frames into buffer
txq.send([pkt] * 2, flush=False)
# send the pending frames
txq.flush()

# send two 64B frame with the same 16B header
txq.send([pkt] * 2, hdrs=hdr)
# send two 64B frame, one with 16B header, one with 32B header
txq.send([pkt] * 2, hdrs=[hdr, hdr + hdr], flags=0)

# send a frame from prepared tuple
msg = (pkt, hdr, 0)
txq.sendmsg([msg])


# Receiving frames
# ----------------

# receive all pending frames
pkts = rxq.recv()
assert len(pkts) == 0 or isinstance(pkts[0], bytes)

# receive all pending frames
# if no frame is available, wait for incoming frames maximally 0.5 sec
pkts = rxq.recv(timeout=0.5)

# try to receive specific count of frames
# returned list can be smaller, if there is not enough pending frames
pkts = rxq.recv(cnt=1)

# try to receive specific count of frames
# if not enough frames is available, wait for incoming frames maximally 2 secs
pkts = rxq.recv(cnt=1, timeout=2)

# receive specific count of frames, wait indefinitely
#rxq.recv(cnt=1, timeout=None)

# receive list of messages
# message is a tuple(pkt: bytes, hdr: bytes, flags: int)
msgs = rxq.recvmsg()
assert len(msgs) == 0 or (isinstance(msgs[0], tuple) and len(msgs[0]) == 3)


The NDP subsystem can transmit or receive data over multiple queues at once.

# 2.B Data transmission on multiple queues
##########################################

# Transmitting frames
# -------------------

# send 64B frame to all queues
ndp.send(pkt)
# send 64B frame to first three queues
ndp.send(pkt, i=[0, 1, 2])
# write 64B frame into buffer of all queues
ndp.send(pkt, flush=False)
# send pending frames on all queues
ndp.flush()

# send a frame from prepared tuple on all queues
ndp.sendmsg(msg)


# Receiving frames
# ----------------

# receive pending frames from all queues
# return value is list of tuple(pkt: bytes, queue_index: int)
pkts = ndp.recv()
assert len(pkts) == 0 or (
    isinstance(pkts[0], tuple) and len(pkts[0]) == 2 and isinstance(pkts[0][0], bytes)
)

# receive pending frames on specific queue
ndp.recv(i=1)
# receive pending frames on first three queues
ndp.recv(i=[0, 1, 2])
# receive specific count of frames from any queues, wait indefinitely
#ndp.recv(timeout=None)

# receive pending messages from all queues, return value is list of tuple(tuple(pkt: bytes, hdr: bytes, flags: int), queue_index: int)
msgs = rxq.recvmsg()
assert len(msgs) == 0 or (
    isinstance(msgs[0], tuple)
    and len(msgs[0]) == 2
    and isinstance(msgs[0][0][0], bytes)
)


Queue statistics can obtained as dictionary and reseted.

# 2.C Queues statistics
#######################

try:
    # stats == {'sent': 4, 'sent_bytes': 276}
    stats = txq.read_stats()

    # Reset Queue statistics
    txq.reset_stats()
except Exception:
    pass