Ask Your Question

Calling "mac-nr" dissector from LUA script results in an error

asked 2022-07-08 00:45:15 +0000

Venkat gravatar image


My usecase is this.

  1. I have a 5G-NR Layer1 to Layer2 Protocol like nFAPI that encapsulates the NR MAC payload such that (UDP->myFAPI->MAC PDU)
  2. I wrote a LUA script to process this FAPI protocol and it works great.
  3. Now I want to parse and print the contents of the MAC PDU .. and in the interest of not re-inventing the wheel i tried to use the existing "mac-nr" like so -> Dissector.get("mac-nr"):call(buffer(pktOffset):tvb(), pinfo, subtree)
  4. Now I get an (expert) error saying "Can't dissect NR MAC frame because no per-frame info was attached!". i.e. the following snippet in -> packet-mac-nr.c -> dissect_mac_nr

    /* Look for packet info! */ p_mac_nr_info = (mac_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_nr, 0);

    /* Can't dissect anything without it... */ if (p_mac_nr_info == NULL) { proto_tree_add_expert(mac_nr_tree, pinfo, &ei_mac_nr_no_per_frame_data, tvb, offset, -1); return 0; }

  5. Upon inspection, it looks like i need to fill this packet info and set it in "pinfo" prior to calling "mac-nr" dissector..

  6. Problem is, i dont know how to do this in LUA for the destination C dissector. And there does not seem to be any posts on this very specific issue (Forgive me if there is one.. and pls point me to it)
  7. Had I written this dissector in C, I would have been able to do this seamlessly (I imagine).

So my question is.. can this be done via the LUA script ? If so how

Any help is appreciated and thanks in advance

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted

answered 2022-07-11 20:29:03 +0000

Venkat gravatar image

updated 2022-07-11 20:29:44 +0000

Hi ... the solution to my particular problem is one of the following

  1. Either write a LUA binding in C for the proto_data and extend the current "mac-nr" dissector

  2. Or build a new custom tvb, in a way that the existing code expects it, as suggested by chuckc ... which seems the simpler thing to do.. to me

So I am going ahead with (2) and it seems to be working and i could atleast proceed with this for now...

And so I am thankful for the help. This is my first question and I am thankful it gave me a way forward. Thanks again chuckc

edit flag offensive delete link more


Hi @Venkat, Could you please provide a code snippet for how you got it working? I trying to get through the same issue but get varying permutations of userinfo expected but got bytearray, or sometimes the opposite. Thanks!

nickh gravatar imagenickh ( 2024-01-12 19:58:36 +0000 )edit

To help anyone else who might want to do this, I found this answer to be the most helpful:

Payload type tags can be found here:

And for NR Uplink, the code below works for me:

--If the mac payload is in tvbuf(): 

local STARTER        = "mac-nr"
local LEN_STARTER    = string.len(STARTER)
local HEX_STARTER    = hexstr(STARTER)

local bytes = HEX_STARTER -- create the string

 -- TDD_Radio, Uplink, C_RNTI, PayloadPduTag
local nr_pdu ="01 01 03 01")
bytes = bytes .. nr_pdu:tohex() -- append to the "mac-nr" string

bytes = bytes .. tostring(tvbuf:range(offset):bytes())

local nr_len = tvbuf:len() - offset + nr_pdu:len() 

-- Print the UDP header with the length
local fake_udp_hdr = string.format('00000000%04x0000', 8  + nr_len + LEN_STARTER)

-- prepend the UDP header
local bytes = fake_udp_hdr .. bytes

-- create the tvb
buf = ByteArray.tvb(, "[NR over UDP]")

--send it to the dissector
Dissector.get("udp"):call(buf, pktinfo, TxDataReqTree)
nickh gravatar imagenickh ( 2024-01-16 17:23:10 +0000 )edit

answered 2022-07-08 03:19:48 +0000

Chuckc gravatar image

Why not pass it the pinfo that was passed into your dissector?

10.3. Example: Dissector written in Lua

function p_multi.dissector(buf, pkt, tree)
        if dissector ~= nil then
                -- Dissector was found, invoke subdissector with a new Tvb,
                -- created from the current buffer (skipping first two bytes).
                dissector:call(buf(2):tvb(), pkt, tree)

Guacamole Dissector - guacp-postdissector.lua

function guacp_post.dissector(tvbuf, pinfo, tree)
    guacp_dissector:call(guacp_tvb:tvb(), pinfo, tree)
edit flag offensive delete link more


Thanks for the reply. And yes I am passing the pinfo that was received by my dissector.

Like so

function my_protocol.dissector(buffer, pinfo, tree)
pktLength = buffer:len()
pktOffset = 0
nextFieldLen = 0
if pktLength == 0 then return end

pinfo.cols.protocol =


pktlen = buffer:reported_length_remaining()

local subtree = tree:add(my_protocol, buffer(), "My FAPI Protocol")

if parseMyFAPIMessage(buffer, pinfo, subtree) == false then return funcReturnHook() end

And the same pinfo is passed down to other sub functions until it reaches to the place where I call ->

Dissector.get("mac-nr"):call(buffer(pktOffset):tvb(), pinfo, subtree)

It appears to me that, inorder to call "mac-nr" dissector, the caller needs to fill extra information which is mandatory for the parsing of the MAC PDU contents... Like SFN, Slot numbers, i.e. the following C Structure

/* Context info attached to each NR MAC frame */    
typedef struct ...
Venkat gravatar imageVenkat ( 2022-07-08 17:48:12 +0000 )edit

Looks like the heuristic dissect_mac_nr_heur() will add the proto_data to the pinfo.
It's in the udp table.
You could try DissectorTable.try_heuristics(listname, tvb, pinfo, tree). ("MAC-NR over UDP" is disabled by default so would need to enable it)

Chuckc gravatar imageChuckc ( 2022-07-08 18:36:37 +0000 )edit

Thanks again for the reply.

But I tried it and it did not work ... Then i checked the dissect_mac_nr_heur() function ... and I think it wont work because it looks for the information in places where my packet would not have them ...

For instance

/* If redissecting, use previous info struct (if available) */
p_mac_nr_info = (mac_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_nr, 0);
if (p_mac_nr_info == NULL) {
    /* Allocate new info struct for this frame */
    p_mac_nr_info = wmem_new0(wmem_file_scope(), mac_nr_info);

    /* Read fixed fields */
    p_mac_nr_info->radioType = tvb_get_guint8(tvb, offset++);
    p_mac_nr_info->direction = tvb_get_guint8(tvb, offset++);
    p_mac_nr_info->rntiType = tvb_get_guint8(tvb, offset++);

radioType, direcion and rntiType are not in this order in my FAPI protocol no matter what offset we use ... So i think this heuristic parsing also will not help. And that I might need another way to fill this "info struct" in LUA while I am parsing the upper layer (FAPI) fields, and pass the filled (LUA table !?) data to the "mac-nr" C ...(more)

Venkat gravatar imageVenkat ( 2022-07-08 18:53:21 +0000 )edit

I think you would have to write a Lua binding in C for the proto_data functions. Beyond me.

If you have the data available that the heuristic is looking for but in the wrong order, you could build a new custom tvb using11.8.1.16. bytearray:tvb(name) and place the data at the proper offsets. This is getting pretty far away from your original question.

Chuckc gravatar imageChuckc ( 2022-07-08 20:33:03 +0000 )edit

That's not a bad idea .. i will give that a try (i.e. to create a new TVB in the expected order)

Venkat gravatar imageVenkat ( 2022-07-08 21:54:13 +0000 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2022-07-08 00:45:15 +0000

Seen: 372 times

Last updated: Jul 11 '22