Skip to content

Conversation

@sneaky-potato
Copy link

This PR add a minimal LLDP example implemented as a Lunatik Lua script. The example uses an AF_PACKET socket to receive and filter LLDP (EtherType 0x88cc) frames and demonstrates raw Ethernet access.

Addresses #126

@lneto
Copy link
Contributor

lneto commented Dec 22, 2025

This PR add a minimal LLDP example implemented as a Lunatik Lua script. The example uses an AF_PACKET socket to receive and filter LLDP (EtherType 0x88cc) frames and demonstrates raw Ethernet access.

Addresses #126

sorry, it's not clear to me what you want to implement here. The referred issue is for implementing a proper LLDP parser, not only to match it's ether type. If you want to extend this implementing a patch, I will be glad to merge; but please, keep this PR as draft while it's not intended to be merged.

@sneaky-potato
Copy link
Author

Thanks for the clarification.

I’ve now updated the example to include a minimal LLDP TLV parser (Chassis ID, Port ID, TTL, System Name, plus generic TLV handling).

I’ll keep the PR as draft for now, please let me know if this level of parsing aligns with what you had in mind, or if you’d prefer additional TLVs or structure before merging.

(Tested this script via a veth pair: lldpd was running on one interface to emit frames)

@sneaky-potato sneaky-potato marked this pull request as draft December 22, 2025 13:31
Comment on lines 41 to 48
if tlv_type == 1 then
table.insert(out, "chassis id")
elseif tlv_type == 2 then
table.insert(out, "port id")
elseif tlv_type == 3 then
local ttl = string.unpack(">I2", value)
table.insert(out, "ttl: " .. ttl)
elseif tlv_type == 5 then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of having this long if-then-else block, you can have a table indexed by tlv_type

@lneto
Copy link
Contributor

lneto commented Dec 22, 2025

Thanks for the clarification.

I’ve now updated the example to include a minimal LLDP TLV parser (Chassis ID, Port ID, TTL, System Name, plus generic TLV handling).

I’ll keep the PR as draft for now, please let me know if this level of parsing aligns with what you had in mind, or if you’d prefer additional TLVs or structure before merging.

(Tested this script via a veth pair: lldpd was running on one interface to emit frames)

indeed it's more aligned now, you're on the right path.. but, we try to have self-contained examples.. in the sense they should be "useful" apps with a specific purpose.. I think to make this example useful, we should have a actual LLDP client or server.. or having a netfilter filter, for instance.. to block or scrap some info..

@sneaky-potato
Copy link
Author

I understand what you mean by making a lldp server client pair but could you clarify what a netfilter filter would do? Do we want to block certain tlv? The client receives lldp frames, inspects them, and then decides whether to allow or drop them. Please tell me in what direction I should drive this PR.

@lneto
Copy link
Contributor

lneto commented Dec 22, 2025

I understand what you mean by making a lldp server client pair but could you clarify what a netfilter filter would do? Do we want to block certain tlv? The client receives lldp frames, inspects them, and then decides whether to allow or drop them. Please tell me in what direction I should drive this PR.

I see three different paths to make it a useful app:

  1. basic LLDP server, using sockets. I think this is the more useful one.
  2. basic LLDP client, also using sockets.
  3. LLDP filter, using netfilter, blocking, modifying or monitoring LLDP responses. You could for instance, keep a RCU table with the known neighbors and retrieve it from the userspace using your driver.

It's actually up to you to decide what to implement =). I found a LLDP server more useful perhaps. However, my only requirement is to make it a "full" example. A useful app ;-).

You are equally free to choose another path. I just don't find the current approach of having another sniffer that useful. You could also extend the sniffer example we already have with a LLDP parser, enriching it. It's up to you =).

@sneaky-potato
Copy link
Author

sneaky-potato commented Dec 23, 2025

Hi @lneto I did a little bit of tinkering with netfilter hooks to filter LLDP frames and put them on a shared RCU table. Right now the reader prints nothing, where can I find good documentation on netfilter? I think the parameters passed in netfilter hook need to be tweaked

Regarding the server, just to confirm, did you mean a thread emitting LLDP frames on a specified interface (will need to get source MAC of the interface somehow to do this)?

local lunatik = require("lunatik")
local rcu = require("rcu")
local linux = require("linux")
local string = require("string")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneeded

end

local function lldp_hook(skb)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

please, mind our code style.

pf = family.BRIDGE,
hooknum = hooks.PRE_ROUTING,
priority = pri.FILTER,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
}

return table.concat(out, "\n") .. "\n"
end

device.new(lldp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
device.new(lldp)
device.new(lldp)

@lneto
Copy link
Contributor

lneto commented Dec 23, 2025

Hi @lneto I did a little bit of tinkering with netfilter hooks to filter LLDP frames and put them on a shared RCU table. Right now the reader prints nothing, where can I find good documentation on netfilter? I think the parameters passed in netfilter hook need to be tweaked

did you try to put some prints on your hook? are you generating LLDP traffic? are you are running the daemon locally? if so, you probably need to use LOCAL_IN. did you take a look at this https://luainkernel.github.io/lunatik/modules/netfilter.html? or are you referring to general netfilter doc? if so, I think it's a good place to get started https://thermalcircle.de/doku.php?id=blog:linux:nftables_packet_flow_netfilter_hooks_detail.

Regarding the server, just to confirm, did you mean a thread emitting LLDP frames on a specified interface (will need to get source MAC of the interface somehow to do this)?

Yes, I meant to implement an lldpd on Lunatik ;-). You can get the MAC address from the frames, right? What's missing?

@sneaky-potato
Copy link
Author

For the netfilter filter, which family should we use for capturing LLDP frames? I think NETDEV should be used but my kernel seem to not support it (arch linux kernel v6.12.63-1-lts) by default (cant see CONFIG_NETFILTER_NETDEV=y). What do you think should be done? Is NETDEV included in kernel binaries by default? I tried with BRIDGE family but that will require a bridge setup for the interfaces.

Yes, I meant to implement an lldpd on Lunatik ;-). You can get the MAC address from the frames, right? What's missing?

Nothing, I'll add the server implementation soon after I figure out the netfilter part

@lneto
Copy link
Contributor

lneto commented Dec 23, 2025

For the netfilter filter, which family should we use for capturing LLDP frames? I think NETDEV should be used but my kernel seem to not support it (arch linux kernel v6.12.63-1-lts) by default (cant see CONFIG_NETFILTER_NETDEV=y). What do you think should be done? Is NETDEV included in kernel binaries by default? I tried with BRIDGE family but that will require a bridge setup for the interfaces.

I don't see why you can't run on BRIDGE.

Yes, I meant to implement an lldpd on Lunatik ;-). You can get the MAC address from the frames, right? What's missing?

Nothing, I'll add the server implementation soon after I figure out the netfilter part

I think we are mixing up things here; my suggestion to implement a server here was by using raw sockets as you were doing before. I suggested 3 different paths, not a mix of them ;-).

A minimal LLDP example implemented as a Lunatik Lua script.
The example uses a thread to emit LLDP (EtherType 0x88cc)
frames and send them on a specified network interface.

Signed-off-by: Ashwani Kumar Kamal <ashwanikamal.im421@gmail.com>
@sneaky-potato
Copy link
Author

I think we are mixing up things here; my suggestion to implement a server #341 (comment) was by using raw sockets as you were doing before. I suggested 3 different paths, not a mix of them ;-).

You are right. A server makes the most sense here. I have added a simple daemon which emits LLDP frames every 30 seconds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants